From 37bc41b098d300e061928b1cb53e68a5f4de7306 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 20 Sep 2023 19:11:56 +0530 Subject: [PATCH 01/89] added resouce service defauls config entry --- consul/resource_provider.go | 53 ++-- .../resource_service_defaults_config_entry.go | 270 ++++++++++++++++++ 2 files changed, 297 insertions(+), 26 deletions(-) create mode 100644 consul/resource_service_defaults_config_entry.go diff --git a/consul/resource_provider.go b/consul/resource_provider.go index 3fc9b62b..818595e1 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -225,32 +225,33 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "consul_acl_auth_method": resourceConsulACLAuthMethod(), - "consul_acl_binding_rule": resourceConsulACLBindingRule(), - "consul_acl_policy": resourceConsulACLPolicy(), - "consul_acl_role": resourceConsulACLRole(), - "consul_acl_token": resourceConsulACLToken(), - "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), - "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), - "consul_admin_partition": resourceConsulAdminPartition(), - "consul_agent_service": resourceConsulAgentService(), - "consul_catalog_entry": resourceConsulCatalogEntry(), - "consul_certificate_authority": resourceConsulCertificateAuthority(), - "consul_config_entry": resourceConsulConfigEntry(), - "consul_keys": resourceConsulKeys(), - "consul_key_prefix": resourceConsulKeyPrefix(), - "consul_license": resourceConsulLicense(), - "consul_namespace": resourceConsulNamespace(), - "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), - "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), - "consul_node": resourceConsulNode(), - "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_autopilot_config": resourceConsulAutopilotConfig(), - "consul_service": resourceConsulService(), - "consul_intention": resourceConsulIntention(), - "consul_network_area": resourceConsulNetworkArea(), - "consul_peering_token": resourceSourceConsulPeeringToken(), - "consul_peering": resourceSourceConsulPeering(), + "consul_acl_auth_method": resourceConsulACLAuthMethod(), + "consul_acl_binding_rule": resourceConsulACLBindingRule(), + "consul_acl_policy": resourceConsulACLPolicy(), + "consul_acl_role": resourceConsulACLRole(), + "consul_acl_token": resourceConsulACLToken(), + "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), + "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), + "consul_admin_partition": resourceConsulAdminPartition(), + "consul_agent_service": resourceConsulAgentService(), + "consul_catalog_entry": resourceConsulCatalogEntry(), + "consul_certificate_authority": resourceConsulCertificateAuthority(), + "consul_config_entry": resourceConsulConfigEntry(), + "consul_keys": resourceConsulKeys(), + "consul_key_prefix": resourceConsulKeyPrefix(), + "consul_license": resourceConsulLicense(), + "consul_namespace": resourceConsulNamespace(), + "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), + "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), + "consul_node": resourceConsulNode(), + "consul_prepared_query": resourceConsulPreparedQuery(), + "consul_autopilot_config": resourceConsulAutopilotConfig(), + "consul_service": resourceConsulService(), + "consul_intention": resourceConsulIntention(), + "consul_network_area": resourceConsulNetworkArea(), + "consul_peering_token": resourceSourceConsulPeeringToken(), + "consul_peering": resourceSourceConsulPeering(), + "consul_service_defaults_config_entry": resourceServiceDefaultsConfigEntry(), }, ConfigureFunc: providerConfigure, diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go new file mode 100644 index 00000000..555011ee --- /dev/null +++ b/consul/resource_service_defaults_config_entry.go @@ -0,0 +1,270 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "encoding/json" + "fmt" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func resourceServiceDefaultsConfigEntry() *schema.Resource { + return &schema.Resource{ + Create: resourceConsulServiceDefaultsConfigEntryUpdate, + Update: resourceConsulServiceDefaultsConfigEntryUpdate, + Read: resourceConsulServiceDefaultsConfigEntryRead, + Delete: resourceConsulServiceDefaultsConfigEntryDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + var kind, name, partition, namespace string + switch len(parts) { + case 2: + kind = parts[0] + name = parts[1] + case 4: + partition = parts[0] + namespace = parts[1] + kind = parts[2] + name = parts[3] + default: + return nil, fmt.Errorf(`expected path of the form "/" or "///"`) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + sw := newStateWriter(d) + sw.set("kind", kind) + sw.set("name", name) + sw.set("partition", partition) + sw.set("namespace", namespace) + + err := sw.error() + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil + }, + }, + + Schema: map[string]*schema.Schema{ + "kind": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The partition the config entry is associated with.", + }, + + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "mode": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "transparent_proxy": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "mutual_tls_mode": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "mesh_gateway": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "expose": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "external_sni": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "upstream_config": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "destination": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "max_inbound_connections": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "local_connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "local_request_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "rate_limits": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + "envoy_extensions": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + }, + } +} + +func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.QueryOptions) { + // exported-services config entries are weird in that their name correspond + // to the partition they are created in, see + // https://www.consul.io/docs/connect/config-entries/exported-services#configuration-parameters + if kind == "exported-services" && name != "default" { + qOpts.Partition = name + } +} + +func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { + client, qOpts, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + + kind := d.Get("kind").(string) + name := d.Get("name").(string) + + fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) + + attributes := []string{"partition", "namespace", "protocol", "mode", "transparent_proxy", "mutual_tls_mode", "mesh_gateway", + "expose", "external_sni", "upstream_config", "destination", "max_inbound_connections", "local_connect_timeout_ms", + "local_request_timeout_ms", "balance_inbound_connections", "rate_limits", "envoy_extensions", "meta"} + + var configJson map[string]interface{} + + for _, attribute := range attributes { + value := d.Get(attribute) + if value != nil { + configJson[attribute] = value + } + } + + err := d.Set("config_json", configJson) + + if err != nil { + return fmt.Errorf("failed to create config json to make config entry") + } + + configEntry, err := makeServiceDefaultsConfigEntry(kind, name, d.Get("config_json").(string), wOpts.Namespace, wOpts.Partition) + if err != nil { + return err + } + + if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { + return fmt.Errorf("failed to set '%s' config entry: %v", name, err) + } + _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + return fmt.Errorf(`failed to read config entry after setting it. +This may happen when some attributes have an unexpected value. +Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html +to see what values are expected`, configEntry.GetKind()) + } + return fmt.Errorf("failed to read config entry: %v", err) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + return resourceConsulServiceDefaultsConfigEntryRead(d, meta) +} + +func resourceConsulServiceDefaultsConfigEntryRead(d *schema.ResourceData, meta interface{}) error { + client, qOpts, _ := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + fixQOptsForConfigEntry(configName, configKind, qOpts) + + _, _, err := configEntries.Get(configKind, configName, qOpts) + if err != nil { + return err + } + + return nil +} + +func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { + client, _, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { + return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) + } + d.SetId("") + return nil +} + +func makeServiceDefaultsConfigEntry(kind, name, config, namespace, partition string) (consulapi.ConfigEntry, error) { + var configMap map[string]interface{} + if err := json.Unmarshal([]byte(config), &configMap); err != nil { + return nil, fmt.Errorf("failed to unmarshal configMap: %v", err) + } + + configMap["kind"] = kind + configMap["name"] = name + configMap["Namespace"] = namespace + configMap["Partition"] = partition + + configEntry, err := consulapi.DecodeConfigEntry(configMap) + if err != nil { + return nil, fmt.Errorf("failed to decode config entry: %v", err) + } + + return configEntry, nil +} From f8f28d738609eb18465f417a45de153965d5e83a Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 22 Sep 2023 15:57:31 +0530 Subject: [PATCH 02/89] working code --- .../resource_service_defaults_config_entry.go | 252 +++++++++++++----- 1 file changed, 187 insertions(+), 65 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index 555011ee..25c9e501 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -4,15 +4,75 @@ package consul import ( - "encoding/json" + "bytes" "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "reflect" + "sort" "strings" consulapi "github.com/hashicorp/consul/api" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + schema "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) func resourceServiceDefaultsConfigEntry() *schema.Resource { + //var upstreamConfigSchema = &schema.Resource{ + // Schema: map[string]*schema.Schema{ + // "name": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "partition": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "namespace": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "peer": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "envoy_listener_json": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "envoy_cluster_json": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "protocol": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "connect_timeout_ms": { + // Type: schema.TypeString, + // Optional: true, + // }, + // "limits": { + // Type: schema.TypeList, + // Optional: true, + // Elem: &schema.Resource{ + // Schema: map[string]*schema.Schema{ + // "max_connections": { + // Type: schema.TypeInt, + // }, + // "max_pending_requests": { + // Type: schema.TypeInt, + // }, + // "max_concurrent_requests": { + // Type: schema.TypeInt, + // }, + // }, + // }, + // }, + // "passive_health_check": { + // Type: schema.TypeList, + // Optional: true, + // }, + // }, + //} return &schema.Resource{ Create: resourceConsulServiceDefaultsConfigEntryUpdate, Update: resourceConsulServiceDefaultsConfigEntryUpdate, @@ -54,8 +114,9 @@ func resourceServiceDefaultsConfigEntry() *schema.Resource { Schema: map[string]*schema.Schema{ "kind": { Type: schema.TypeString, - Required: true, + Required: false, ForceNew: true, + Computed: true, }, "name": { @@ -64,98 +125,136 @@ func resourceServiceDefaultsConfigEntry() *schema.Resource { ForceNew: true, }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { Type: schema.TypeString, Optional: true, - ForceNew: true, Description: "The partition the config entry is associated with.", }, - "namespace": { - Type: schema.TypeString, + "meta": { + Type: schema.TypeMap, Optional: true, - ForceNew: true, }, "protocol": { Type: schema.TypeString, Required: true, - ForceNew: true, }, + + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + "mode": { Type: schema.TypeString, Optional: true, - ForceNew: true, }, + + //"upstream_config": { + // Type: schema.TypeList, + // Optional: true, + // Elem: upstreamConfigSchema, + //}, + "transparent_proxy": { - Type: schema.TypeMap, + Type: schema.TypeSet, Optional: true, - ForceNew: true, + 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, - ForceNew: true, }, "mesh_gateway": { - Type: schema.TypeMap, + Type: schema.TypeSet, Optional: true, - ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Required: true, + Type: schema.TypeString, + }, + }, + }, }, "expose": { - Type: schema.TypeMap, - Optional: true, - ForceNew: true, + Type: schema.TypeSet, + Required: true, + 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.Schema{Type: schema.TypeString}, + }, + }, + }, }, "external_sni": { Type: schema.TypeString, Optional: true, - ForceNew: true, - }, - "upstream_config": { - Type: schema.TypeMap, - Optional: true, - ForceNew: true, }, "destination": { - Type: schema.TypeMap, - Optional: true, - ForceNew: true, + Type: schema.TypeSet, + Required: true, + 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}, + }, + }, + }, + Set: resourceConsulServiceDefaultsDestinationHash, }, "max_inbound_connections": { Type: schema.TypeInt, Optional: true, - ForceNew: true, }, "local_connect_timeout_ms": { Type: schema.TypeInt, Optional: true, - ForceNew: true, }, "local_request_timeout_ms": { Type: schema.TypeInt, Optional: true, - ForceNew: true, - }, - "balance_inbound_connections": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, }, "rate_limits": { Type: schema.TypeMap, Optional: true, - ForceNew: true, }, "envoy_extensions": { Type: schema.TypeList, Optional: true, - ForceNew: true, - }, - "meta": { - Type: schema.TypeMap, - Optional: true, - ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeMap}, }, }, } @@ -174,31 +273,39 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta client, qOpts, wOpts := getClient(d, meta) configEntries := client.ConfigEntries() - kind := d.Get("kind").(string) name := d.Get("name").(string) - fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) + configMap := make(map[string]interface{}) + + configMap["kind"] = "service-defaults" + configMap["name"] = name - attributes := []string{"partition", "namespace", "protocol", "mode", "transparent_proxy", "mutual_tls_mode", "mesh_gateway", - "expose", "external_sni", "upstream_config", "destination", "max_inbound_connections", "local_connect_timeout_ms", - "local_request_timeout_ms", "balance_inbound_connections", "rate_limits", "envoy_extensions", "meta"} + kind := configMap["kind"].(string) + d.Set("kind", kind) - var configJson map[string]interface{} + fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) + + attributes := []string{"partition", "namespace", + "protocol", "mode", "transparent_proxy", + "mutual_tls_mode", "mesh_gateway", + "expose", "external_sni", + "upstream_config", "destination", + "max_inbound_connections", "local_connect_timeout_ms", + "local_request_timeout_ms", "balance_inbound_connections", + "rate_limits", "envoy_extensions", "meta"} for _, attribute := range attributes { value := d.Get(attribute) if value != nil { - configJson[attribute] = value + configMap[attribute] = value } } - err := d.Set("config_json", configJson) - - if err != nil { - return fmt.Errorf("failed to create config json to make config entry") - } + destinationSet := configMap["destination"].(*schema.Set) + destinationList := destinationSet.List() + configMap["destination"] = destinationList[0] - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, d.Get("config_json").(string), wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceDefaultsConfigEntry(kind, name, configMap, wOpts.Namespace, wOpts.Partition) if err != nil { return err } @@ -230,11 +337,7 @@ func resourceConsulServiceDefaultsConfigEntryRead(d *schema.ResourceData, meta i fixQOptsForConfigEntry(configName, configKind, qOpts) _, _, err := configEntries.Get(configKind, configName, qOpts) - if err != nil { - return err - } - - return nil + return err } func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { @@ -250,12 +353,7 @@ func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta return nil } -func makeServiceDefaultsConfigEntry(kind, name, config, namespace, partition string) (consulapi.ConfigEntry, error) { - var configMap map[string]interface{} - if err := json.Unmarshal([]byte(config), &configMap); err != nil { - return nil, fmt.Errorf("failed to unmarshal configMap: %v", err) - } - +func makeServiceDefaultsConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { configMap["kind"] = kind configMap["name"] = name configMap["Namespace"] = namespace @@ -268,3 +366,27 @@ func makeServiceDefaultsConfigEntry(kind, name, config, namespace, partition str return configEntry, nil } + +func resourceConsulServiceDefaultsDestinationHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["port"].(int))) + addresses := reflect.ValueOf(m["addresses"]) + for i := 0; i < addresses.Len(); i++ { + address := addresses.Index(i) + buf.WriteString(fmt.Sprintf("%d-", address)) + } + if v, ok := m["tags"]; ok { + vs := v.(*schema.Set).List() + s := make([]string, len(vs)) + for i, raw := range vs { + s[i] = raw.(string) + } + sort.Strings(s) + + for _, v := range s { + buf.WriteString(fmt.Sprintf("%s-", v)) + } + } + return hashcode.String(buf.String()) +} From ef0297182f0e4887c58eb3fdd2f050c24fcbc535 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 22 Sep 2023 16:13:58 +0530 Subject: [PATCH 03/89] some prog --- .../resource_service_defaults_config_entry.go | 151 +++++++++++------- 1 file changed, 89 insertions(+), 62 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index 25c9e501..43fe3f1d 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -16,63 +16,90 @@ import ( ) func resourceServiceDefaultsConfigEntry() *schema.Resource { - //var upstreamConfigSchema = &schema.Resource{ - // Schema: map[string]*schema.Schema{ - // "name": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "partition": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "namespace": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "peer": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "envoy_listener_json": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "envoy_cluster_json": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "protocol": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "connect_timeout_ms": { - // Type: schema.TypeString, - // Optional: true, - // }, - // "limits": { - // Type: schema.TypeList, - // Optional: true, - // Elem: &schema.Resource{ - // Schema: map[string]*schema.Schema{ - // "max_connections": { - // Type: schema.TypeInt, - // }, - // "max_pending_requests": { - // Type: schema.TypeInt, - // }, - // "max_concurrent_requests": { - // Type: schema.TypeInt, - // }, - // }, - // }, - // }, - // "passive_health_check": { - // Type: schema.TypeList, - // Optional: true, - // }, - // }, - //} + upstreamConfigSchema := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_listener_json": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_cluster_json": { + Type: schema.TypeString, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + }, + "connect_timeout_ms": { + Type: schema.TypeString, + Optional: true, + }, + "limits": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "passive_health_check": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeInt, + Optional: true, + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + }, + "base_ejection_time": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + }, + } return &schema.Resource{ Create: resourceConsulServiceDefaultsConfigEntryUpdate, Update: resourceConsulServiceDefaultsConfigEntryUpdate, @@ -156,11 +183,11 @@ func resourceServiceDefaultsConfigEntry() *schema.Resource { Optional: true, }, - //"upstream_config": { - // Type: schema.TypeList, - // Optional: true, - // Elem: upstreamConfigSchema, - //}, + "upstream_config": { + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchema, + }, "transparent_proxy": { Type: schema.TypeSet, From b4554cfb58733ece01763dc9e7fd73a6dc354aae Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 23 Sep 2023 10:38:34 +0530 Subject: [PATCH 04/89] working code --- .../resource_service_defaults_config_entry.go | 547 ++++++++++-------- 1 file changed, 315 insertions(+), 232 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index 43fe3f1d..f81bc517 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -15,91 +15,318 @@ import ( schema "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -func resourceServiceDefaultsConfigEntry() *schema.Resource { - upstreamConfigSchema := &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, +var upstreamConfigSchema = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_listener_json": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_cluster_json": { + Type: schema.TypeString, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + }, + "connect_timeout_ms": { + Type: schema.TypeString, + Optional: true, + }, + "limits": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + }, + }, }, - "namespace": { - Type: schema.TypeString, - Optional: true, + }, + "passive_health_check": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeInt, + Optional: true, + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + }, + "base_ejection_time": { + Type: schema.TypeInt, + Optional: true, + }, + }, }, - "peer": { - Type: schema.TypeString, - Optional: true, + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + }, + }, }, - "envoy_listener_json": { - Type: schema.TypeString, - Optional: true, + }, + "balance_outbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + }, +} + +var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ + "kind": { + Type: schema.TypeString, + Required: false, + ForceNew: true, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + + "partition": { + Type: schema.TypeString, + Optional: true, + Description: "The partition the config entry is associated with.", + }, + + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + }, + + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + + "mode": { + Type: schema.TypeString, + Optional: true, + }, + + "upstream_config": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "overrides": { + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchema, + }, + "defaults": { + Type: schema.TypeSet, + Optional: true, + Elem: upstreamConfigSchema, + }, }, - "envoy_cluster_json": { - Type: schema.TypeString, - Optional: true, + }, + }, + + "transparent_proxy": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "outbound_listener_port": { + Required: true, + Type: schema.TypeInt, + }, + "dialed_directly": { + Required: true, + Type: schema.TypeBool, + }, }, - "protocol": { - Type: schema.TypeString, - Optional: true, + }, + }, + + "mutual_tls_mode": { + Type: schema.TypeString, + Optional: true, + }, + + "envoy_extensions": { + Type: schema.TypeList, + Optional: true, + 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, + }, }, - "connect_timeout_ms": { - Type: schema.TypeString, - Optional: true, + }, + }, + + "destination": { + Type: schema.TypeSet, + Required: true, + 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}, + }, }, - "limits": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "max_connections": { - Type: schema.TypeInt, - Optional: true, - }, - "max_pending_requests": { - Type: schema.TypeInt, - Optional: true, - }, - "max_concurrent_requests": { - Type: schema.TypeInt, - Optional: true, - }, - }, + }, + Set: resourceConsulServiceDefaultsDestinationHash, + }, + + "local_connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + + "max_inbound_connections": { + Type: schema.TypeInt, + Optional: true, + }, + + "local_request_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Required: true, + Type: schema.TypeString, }, }, - "passive_health_check": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "interval": { - Type: schema.TypeInt, - Optional: true, - }, - "max_failures": { - Type: schema.TypeInt, - Optional: true, - }, - "enforcing_consecutive_5xx": { - Type: schema.TypeInt, - Optional: true, - }, - "max_ejection_percent": { - Type: schema.TypeInt, - Optional: true, - }, - "base_ejection_time": { - Type: schema.TypeInt, - Optional: true, + }, + }, + + "external_sni": { + Type: schema.TypeString, + Optional: true, + }, + + "expose": { + Type: schema.TypeSet, + Required: true, + 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 resourceServiceDefaultsConfigEntry() *schema.Resource { + return &schema.Resource{ Create: resourceConsulServiceDefaultsConfigEntryUpdate, Update: resourceConsulServiceDefaultsConfigEntryUpdate, @@ -137,153 +364,7 @@ func resourceServiceDefaultsConfigEntry() *schema.Resource { return []*schema.ResourceData{d}, nil }, }, - - Schema: map[string]*schema.Schema{ - "kind": { - Type: schema.TypeString, - Required: false, - ForceNew: true, - Computed: true, - }, - - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - - "partition": { - Type: schema.TypeString, - Optional: true, - Description: "The partition the config entry is associated with.", - }, - - "meta": { - Type: schema.TypeMap, - Optional: true, - }, - - "protocol": { - Type: schema.TypeString, - Required: true, - }, - - "balance_inbound_connections": { - Type: schema.TypeString, - Optional: true, - }, - - "mode": { - Type: schema.TypeString, - Optional: true, - }, - - "upstream_config": { - Type: schema.TypeList, - Optional: true, - Elem: upstreamConfigSchema, - }, - - "transparent_proxy": { - Type: schema.TypeSet, - Optional: true, - 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, - }, - "mesh_gateway": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Required: true, - Type: schema.TypeString, - }, - }, - }, - }, - "expose": { - Type: schema.TypeSet, - Required: true, - 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.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "external_sni": { - Type: schema.TypeString, - Optional: true, - }, - "destination": { - Type: schema.TypeSet, - Required: true, - 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}, - }, - }, - }, - Set: resourceConsulServiceDefaultsDestinationHash, - }, - "max_inbound_connections": { - Type: schema.TypeInt, - Optional: true, - }, - "local_connect_timeout_ms": { - Type: schema.TypeInt, - Optional: true, - }, - "local_request_timeout_ms": { - Type: schema.TypeInt, - Optional: true, - }, - "rate_limits": { - Type: schema.TypeMap, - Optional: true, - }, - "envoy_extensions": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeMap}, - }, - }, + Schema: serviceDefaultsConfigEntrySchema, } } @@ -303,35 +384,37 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta name := d.Get("name").(string) configMap := make(map[string]interface{}) - configMap["kind"] = "service-defaults" + configMap["name"] = name kind := configMap["kind"].(string) - d.Set("kind", kind) + err := d.Set("kind", kind) + + if err != nil { + return err + } fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) - attributes := []string{"partition", "namespace", - "protocol", "mode", "transparent_proxy", - "mutual_tls_mode", "mesh_gateway", - "expose", "external_sni", - "upstream_config", "destination", - "max_inbound_connections", "local_connect_timeout_ms", - "local_request_timeout_ms", "balance_inbound_connections", - "rate_limits", "envoy_extensions", "meta"} + var attributes []string + + for key, _ := range serviceDefaultsConfigEntrySchema { + attributes = append(attributes, key) + } for _, attribute := range attributes { value := d.Get(attribute) if value != nil { configMap[attribute] = value + switch reflect.TypeOf(value).String() { + case "*schema.Set": + valueList := value.(*schema.Set).List() + configMap[attribute] = valueList[0] + } } } - destinationSet := configMap["destination"].(*schema.Set) - destinationList := destinationSet.List() - configMap["destination"] = destinationList[0] - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, configMap, wOpts.Namespace, wOpts.Partition) if err != nil { return err From 430bb6456375dfd2fd33a3a6fb8bbc21fc73f707 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 23 Sep 2023 11:34:12 +0530 Subject: [PATCH 05/89] fixes --- .../resource_service_defaults_config_entry.go | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index f81bc517..c62d9d6d 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -377,6 +377,34 @@ func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.Q } } +func formatKey(key string) string { + tokens := strings.Split(key, "_") + res := "" + for _, token := range tokens { + if token == "tls" { + res += strings.ToUpper(token) + } else { + res += strings.ToTitle(token) + } + } + return res +} + +func formatMapKeys(m map[string]interface{}, formatFunc func(string) string) map[string]interface{} { + formattedMap := make(map[string]interface{}) + for key, value := range m { + formattedKey := formatFunc(key) + + if nestedMap, isNestedMap := value.(map[string]interface{}); isNestedMap { + formattedValue := formatMapKeys(nestedMap, formatFunc) + formattedMap[formattedKey] = formattedValue + } else { + formattedMap[formattedKey] = value + } + } + return formattedMap +} + func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { client, qOpts, wOpts := getClient(d, meta) configEntries := client.ConfigEntries() @@ -410,16 +438,25 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta switch reflect.TypeOf(value).String() { case "*schema.Set": valueList := value.(*schema.Set).List() - configMap[attribute] = valueList[0] + if len(valueList) > 0 { + configMap[attribute] = valueList[0] + } else { + delete(configMap, attribute) + } } } } - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, configMap, wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formatMapKeys(configMap, formatKey), + wOpts.Namespace, wOpts.Partition) if err != nil { return err } + fmt.Println("config entry decoded") + sericeDefaultCE := configEntry.(*consulapi.ServiceConfigEntry) + fmt.Println(sericeDefaultCE.TransparentProxy) + if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { return fmt.Errorf("failed to set '%s' config entry: %v", name, err) } From 7c7ce968005df3134963bbcaa8851338e6e38cb0 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 23 Sep 2023 18:27:02 +0530 Subject: [PATCH 06/89] fix import --- consul/resource_service_defaults_config_entry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index c62d9d6d..5e97102e 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -12,7 +12,7 @@ import ( "strings" consulapi "github.com/hashicorp/consul/api" - schema "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) var upstreamConfigSchema = &schema.Resource{ From 7be801d8e0af3be42d0e4824727cba30c1772ec5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 13:32:34 +0530 Subject: [PATCH 07/89] final changes without tests --- .../resource_service_defaults_config_entry.go | 111 +++++++++++++----- 1 file changed, 82 insertions(+), 29 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index 5e97102e..22eef943 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -5,6 +5,7 @@ package consul import ( "bytes" + "encoding/json" "fmt" "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "reflect" @@ -235,7 +236,7 @@ var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ "destination": { Type: schema.TypeSet, - Required: true, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "port": { @@ -390,19 +391,81 @@ func formatKey(key string) string { return res } -func formatMapKeys(m map[string]interface{}, formatFunc func(string) string) map[string]interface{} { - formattedMap := make(map[string]interface{}) - for key, value := range m { - formattedKey := formatFunc(key) +func isSlice(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array +} - if nestedMap, isNestedMap := value.(map[string]interface{}); isNestedMap { - formattedValue := formatMapKeys(nestedMap, formatFunc) - formattedMap[formattedKey] = formattedValue - } else { - formattedMap[formattedKey] = value +func isMap(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Map +} + +func isSetSchema(v interface{}) bool { + return reflect.TypeOf(v).String() == "*schema.Set" +} + +func isStruct(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Struct +} + +func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { + if isMap(config) { + fmt.Println("isMap", config) + formattedMap := make(map[string]interface{}) + for key, value := range config.(map[string]interface{}) { + formattedKey := formatFunc(key) + formattedValue, err := formatKeys(value, formatKey) + if err != nil { + return nil, err + } + if formattedValue != nil { + formattedMap[formattedKey] = formattedValue + } + } + return formattedMap, nil + } else if isSlice(config) { + fmt.Println("isSlice", config) + var newSlice []interface{} + listValue := config.([]interface{}) + for _, elem := range listValue { + newElem, err := formatKeys(elem, formatKey) + if err != nil { + return nil, err + } + newSlice = append(newSlice, newElem) + } + return newSlice, nil + } else if isStruct(config) { + fmt.Println("isStruct", config) + var modifiedStruct map[string]interface{} + jsonValue, err := json.Marshal(config) + if err != nil { + return nil, err + } + err = json.Unmarshal(jsonValue, &modifiedStruct) + if err != nil { + return nil, err + } + formattedStructKeys, err := formatKeys(modifiedStruct, formatKey) + if err != nil { + return nil, err } + return formattedStructKeys, nil + } else if isSetSchema(config) { + fmt.Println("isSetSchema", config) + valueList := config.(*schema.Set).List() + if len(valueList) > 0 { + formattedSetValue, err := formatKeys(valueList[0], formatKey) + fmt.Println("formatted set value", formattedSetValue) + if err != nil { + return nil, err + } + return formattedSetValue, nil + } + return nil, nil + } else { + fmt.Println("Type not found - hence not modifying keys", config) } - return formattedMap + return config, nil } func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { @@ -432,30 +495,20 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta } for _, attribute := range attributes { - value := d.Get(attribute) - if value != nil { - configMap[attribute] = value - switch reflect.TypeOf(value).String() { - case "*schema.Set": - valueList := value.(*schema.Set).List() - if len(valueList) > 0 { - configMap[attribute] = valueList[0] - } else { - delete(configMap, attribute) - } - } - } + configMap[attribute] = d.Get(attribute) } - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formatMapKeys(configMap, formatKey), - wOpts.Namespace, wOpts.Partition) + formattedMap, err := formatKeys(configMap, formatKey) if err != nil { return err } - fmt.Println("config entry decoded") - sericeDefaultCE := configEntry.(*consulapi.ServiceConfigEntry) - fmt.Println(sericeDefaultCE.TransparentProxy) + fmt.Println("formattedmap = ", formattedMap.(string)) + + configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + if err != nil { + return err + } if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { return fmt.Errorf("failed to set '%s' config entry: %v", name, err) From b610737cdc7d1490038f78e1fae3588780fdba30 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 16:29:47 +0530 Subject: [PATCH 08/89] test --- .../resource_service_defaults_config_entry.go | 45 ++----------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index 22eef943..c8566733 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -4,12 +4,9 @@ package consul import ( - "bytes" "encoding/json" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "reflect" - "sort" "strings" consulapi "github.com/hashicorp/consul/api" @@ -250,7 +247,6 @@ var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ }, }, }, - Set: resourceConsulServiceDefaultsDestinationHash, }, "local_connect_timeout_ms": { @@ -380,15 +376,15 @@ func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.Q func formatKey(key string) string { tokens := strings.Split(key, "_") - res := "" + keyToReturn := "" for _, token := range tokens { if token == "tls" { - res += strings.ToUpper(token) + keyToReturn += strings.ToUpper(token) } else { - res += strings.ToTitle(token) + keyToReturn += strings.ToTitle(token) } } - return res + return keyToReturn } func isSlice(v interface{}) bool { @@ -409,7 +405,6 @@ func isStruct(v interface{}) bool { func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { if isMap(config) { - fmt.Println("isMap", config) formattedMap := make(map[string]interface{}) for key, value := range config.(map[string]interface{}) { formattedKey := formatFunc(key) @@ -423,7 +418,6 @@ func formatKeys(config interface{}, formatFunc func(string) string) (interface{} } return formattedMap, nil } else if isSlice(config) { - fmt.Println("isSlice", config) var newSlice []interface{} listValue := config.([]interface{}) for _, elem := range listValue { @@ -435,7 +429,6 @@ func formatKeys(config interface{}, formatFunc func(string) string) (interface{} } return newSlice, nil } else if isStruct(config) { - fmt.Println("isStruct", config) var modifiedStruct map[string]interface{} jsonValue, err := json.Marshal(config) if err != nil { @@ -451,19 +444,15 @@ func formatKeys(config interface{}, formatFunc func(string) string) (interface{} } return formattedStructKeys, nil } else if isSetSchema(config) { - fmt.Println("isSetSchema", config) valueList := config.(*schema.Set).List() if len(valueList) > 0 { formattedSetValue, err := formatKeys(valueList[0], formatKey) - fmt.Println("formatted set value", formattedSetValue) if err != nil { return nil, err } return formattedSetValue, nil } return nil, nil - } else { - fmt.Println("Type not found - hence not modifying keys", config) } return config, nil } @@ -503,8 +492,6 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta return err } - fmt.Println("formattedmap = ", formattedMap.(string)) - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) if err != nil { return err @@ -566,27 +553,3 @@ func makeServiceDefaultsConfigEntry(kind, name string, configMap map[string]inte return configEntry, nil } - -func resourceConsulServiceDefaultsDestinationHash(v interface{}) int { - var buf bytes.Buffer - m := v.(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%s-", m["port"].(int))) - addresses := reflect.ValueOf(m["addresses"]) - for i := 0; i < addresses.Len(); i++ { - address := addresses.Index(i) - buf.WriteString(fmt.Sprintf("%d-", address)) - } - if v, ok := m["tags"]; ok { - vs := v.(*schema.Set).List() - s := make([]string, len(vs)) - for i, raw := range vs { - s[i] = raw.(string) - } - sort.Strings(s) - - for _, v := range s { - buf.WriteString(fmt.Sprintf("%s-", v)) - } - } - return hashcode.String(buf.String()) -} From 928f582b808c2e41fd7eb3a70afa122aafcb8979 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 16:37:53 +0530 Subject: [PATCH 09/89] tests for ce working --- ...e_service_defaults_config_entry_ce_test.go | 310 ++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 consul/resource_service_defaults_config_entry_ce_test.go diff --git a/consul/resource_service_defaults_config_entry_ce_test.go b/consul/resource_service_defaults_config_entry_ce_test.go new file mode 100644 index 00000000..1de7afe4 --- /dev/null +++ b/consul/resource_service_defaults_config_entry_ce_test.go @@ -0,0 +1,310 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulServiceDefaultsConfigEntryTest(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_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfig, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exlusive. +const testConsulServiceDefaultsConfigEntryWithDestination = ` +resource "consul_service_defaults_config_entry" "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_service_defaults_config_entry" "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 = 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" + } + } +} +` From fad17492d59d22d0c7b9739f9d5cc461d83b187e Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 16:58:13 +0530 Subject: [PATCH 10/89] added ee tests --- ...e_service_defaults_config_entry_ce_test.go | 2 +- ...e_service_defaults_config_entry_ee_test.go | 318 ++++++++++++++++++ 2 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 consul/resource_service_defaults_config_entry_ee_test.go diff --git a/consul/resource_service_defaults_config_entry_ce_test.go b/consul/resource_service_defaults_config_entry_ce_test.go index 1de7afe4..c5f3d44f 100644 --- a/consul/resource_service_defaults_config_entry_ce_test.go +++ b/consul/resource_service_defaults_config_entry_ce_test.go @@ -8,7 +8,7 @@ import ( "testing" ) -func TestAccConsulServiceDefaultsConfigEntryTest(t *testing.T) { +func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { providers, _ := startTestServer(t) resource.Test(t, resource.TestCase{ diff --git a/consul/resource_service_defaults_config_entry_ee_test.go b/consul/resource_service_defaults_config_entry_ee_test.go new file mode 100644 index 00000000..1b27dfe1 --- /dev/null +++ b/consul/resource_service_defaults_config_entry_ee_test.go @@ -0,0 +1,318 @@ +// 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_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfigEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exlusive. +const testConsulServiceDefaultsConfigEntryWithDestinationEE = ` +resource "consul_service_defaults_config_entry" "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_service_defaults_config_entry" "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" + } + } +} +` From bfd4810c02ad04981e562bd86549bd59f0e54460 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 17:11:43 +0530 Subject: [PATCH 11/89] force new --- consul/resource_service_defaults_config_entry.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index c8566733..db44c244 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -131,11 +131,13 @@ var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ "namespace": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, "partition": { Type: schema.TypeString, Optional: true, + ForceNew: true, Description: "The partition the config entry is associated with.", }, From 7c7f34060da4120880eb2cc5998c9ea751fc0584 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 18:58:36 +0530 Subject: [PATCH 12/89] service splitter --- ...ce_consul_service_splitter_config_entry.go | 342 ++++++++++++++++++ consul/resource_provider.go | 53 +-- 2 files changed, 369 insertions(+), 26 deletions(-) create mode 100644 consul/resource_consul_service_splitter_config_entry.go diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go new file mode 100644 index 00000000..c1c3cf2a --- /dev/null +++ b/consul/resource_consul_service_splitter_config_entry.go @@ -0,0 +1,342 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var serviceSplitterConfigEntrySchema = map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "kind": { + Type: schema.TypeString, + Required: false, + ForceNew: true, + Computed: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "splits": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "weight": { + Type: schema.TypeInt, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "request_headers": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "set": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "remove": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "response_headers": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "set": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "remove": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + }, + }, + }, +} + +func resourceServiceSplitterConfigEntry() *schema.Resource { + + return &schema.Resource{ + Create: resourceConsulServiceSplitterConfigEntryUpdate, + Update: resourceConsulServiceSplitterConfigEntryUpdate, + Read: resourceConsulServiceSplitterConfigEntryRead, + Delete: resourceConsulServiceSplitterConfigEntryDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + var kind, name, partition, namespace string + switch len(parts) { + case 2: + kind = parts[0] + name = parts[1] + case 4: + partition = parts[0] + namespace = parts[1] + kind = parts[2] + name = parts[3] + default: + return nil, fmt.Errorf(`expected path of the form "/" or "///"`) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + sw := newStateWriter(d) + sw.set("kind", kind) + sw.set("name", name) + sw.set("partition", partition) + sw.set("namespace", namespace) + + err := sw.error() + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil + }, + }, + Schema: serviceSplitterConfigEntrySchema, + } +} + +func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.QueryOptions) { + // exported-services config entries are weird in that their name correspond + // to the partition they are created in, see + // https://www.consul.io/docs/connect/config-entries/exported-services#configuration-parameters + if kind == "exported-services" && name != "default" { + qOpts.Partition = name + } +} + +func formatKey(key string) string { + tokens := strings.Split(key, "_") + keyToReturn := "" + for _, token := range tokens { + keyToReturn += strings.ToTitle(token) + } + return keyToReturn +} + +func isSlice(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array +} + +func isMap(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Map +} + +func isSetSchema(v interface{}) bool { + return reflect.TypeOf(v).String() == "*schema.Set" +} + +func isStruct(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Struct +} + +func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { + if isMap(config) { + formattedMap := make(map[string]interface{}) + for key, value := range config.(map[string]interface{}) { + formattedKey := formatFunc(key) + formattedValue, err := formatKeys(value, formatKey) + if err != nil { + return nil, err + } + if formattedValue != nil { + formattedMap[formattedKey] = formattedValue + } + } + return formattedMap, nil + } else if isSlice(config) { + var newSlice []interface{} + listValue := config.([]interface{}) + for _, elem := range listValue { + newElem, err := formatKeys(elem, formatKey) + if err != nil { + return nil, err + } + newSlice = append(newSlice, newElem) + } + return newSlice, nil + } else if isStruct(config) { + var modifiedStruct map[string]interface{} + jsonValue, err := json.Marshal(config) + if err != nil { + return nil, err + } + err = json.Unmarshal(jsonValue, &modifiedStruct) + if err != nil { + return nil, err + } + formattedStructKeys, err := formatKeys(modifiedStruct, formatKey) + if err != nil { + return nil, err + } + return formattedStructKeys, nil + } else if isSetSchema(config) { + valueList := config.(*schema.Set).List() + if len(valueList) > 0 { + formattedSetValue, err := formatKeys(valueList[0], formatKey) + if err != nil { + return nil, err + } + return formattedSetValue, nil + } + return nil, nil + } + return config, nil +} + +func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { + client, qOpts, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + + name := d.Get("name").(string) + + configMap := make(map[string]interface{}) + configMap["kind"] = "service-defaults" + + configMap["name"] = name + + kind := configMap["kind"].(string) + err := d.Set("kind", kind) + + if err != nil { + return err + } + + fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) + + var attributes []string + + for key, _ := range serviceSplitterConfigEntrySchema { + attributes = append(attributes, key) + } + + for _, attribute := range attributes { + configMap[attribute] = d.Get(attribute) + } + + formattedMap, err := formatKeys(configMap, formatKey) + if err != nil { + return err + } + + configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + if err != nil { + return err + } + + if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { + return fmt.Errorf("failed to set '%s' config entry: %v", name, err) + } + _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + return fmt.Errorf(`failed to read config entry after setting it. +This may happen when some attributes have an unexpected value. +Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html +to see what values are expected`, configEntry.GetKind()) + } + return fmt.Errorf("failed to read config entry: %v", err) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + return resourceConsulServiceSplitterConfigEntryRead(d, meta) +} + +func resourceConsulServiceSplitterConfigEntryRead(d *schema.ResourceData, meta interface{}) error { + client, qOpts, _ := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + fixQOptsForConfigEntry(configName, configKind, qOpts) + + _, _, err := configEntries.Get(configKind, configName, qOpts) + return err +} + +func resourceConsulServiceSplitterConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { + client, _, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { + return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) + } + d.SetId("") + return nil +} + +func makeServiceDefaultsConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { + configMap["kind"] = kind + configMap["name"] = name + configMap["Namespace"] = namespace + configMap["Partition"] = partition + + configEntry, err := consulapi.DecodeConfigEntry(configMap) + if err != nil { + return nil, fmt.Errorf("failed to decode config entry: %v", err) + } + + return configEntry, nil +} diff --git a/consul/resource_provider.go b/consul/resource_provider.go index 3fc9b62b..d7604f33 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -225,32 +225,33 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "consul_acl_auth_method": resourceConsulACLAuthMethod(), - "consul_acl_binding_rule": resourceConsulACLBindingRule(), - "consul_acl_policy": resourceConsulACLPolicy(), - "consul_acl_role": resourceConsulACLRole(), - "consul_acl_token": resourceConsulACLToken(), - "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), - "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), - "consul_admin_partition": resourceConsulAdminPartition(), - "consul_agent_service": resourceConsulAgentService(), - "consul_catalog_entry": resourceConsulCatalogEntry(), - "consul_certificate_authority": resourceConsulCertificateAuthority(), - "consul_config_entry": resourceConsulConfigEntry(), - "consul_keys": resourceConsulKeys(), - "consul_key_prefix": resourceConsulKeyPrefix(), - "consul_license": resourceConsulLicense(), - "consul_namespace": resourceConsulNamespace(), - "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), - "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), - "consul_node": resourceConsulNode(), - "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_autopilot_config": resourceConsulAutopilotConfig(), - "consul_service": resourceConsulService(), - "consul_intention": resourceConsulIntention(), - "consul_network_area": resourceConsulNetworkArea(), - "consul_peering_token": resourceSourceConsulPeeringToken(), - "consul_peering": resourceSourceConsulPeering(), + "consul_acl_auth_method": resourceConsulACLAuthMethod(), + "consul_acl_binding_rule": resourceConsulACLBindingRule(), + "consul_acl_policy": resourceConsulACLPolicy(), + "consul_acl_role": resourceConsulACLRole(), + "consul_acl_token": resourceConsulACLToken(), + "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), + "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), + "consul_admin_partition": resourceConsulAdminPartition(), + "consul_agent_service": resourceConsulAgentService(), + "consul_catalog_entry": resourceConsulCatalogEntry(), + "consul_certificate_authority": resourceConsulCertificateAuthority(), + "consul_config_entry": resourceConsulConfigEntry(), + "consul_keys": resourceConsulKeys(), + "consul_key_prefix": resourceConsulKeyPrefix(), + "consul_license": resourceConsulLicense(), + "consul_namespace": resourceConsulNamespace(), + "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), + "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), + "consul_node": resourceConsulNode(), + "consul_prepared_query": resourceConsulPreparedQuery(), + "consul_autopilot_config": resourceConsulAutopilotConfig(), + "consul_service": resourceConsulService(), + "consul_intention": resourceConsulIntention(), + "consul_network_area": resourceConsulNetworkArea(), + "consul_peering_token": resourceSourceConsulPeeringToken(), + "consul_peering": resourceSourceConsulPeering(), + "consul_service_splitter_config_entry": resourceServiceSplitterConfigEntry(), }, ConfigureFunc: providerConfigure, From 37746be693841e4f4d1b2ce229082f44d4153fcf Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 25 Sep 2023 19:34:47 +0530 Subject: [PATCH 13/89] fixes during testing --- consul/resource_consul_service_splitter_config_entry.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go index c1c3cf2a..004416c6 100644 --- a/consul/resource_consul_service_splitter_config_entry.go +++ b/consul/resource_consul_service_splitter_config_entry.go @@ -251,7 +251,7 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta name := d.Get("name").(string) configMap := make(map[string]interface{}) - configMap["kind"] = "service-defaults" + configMap["kind"] = "service-splitter" configMap["name"] = name @@ -279,7 +279,7 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta return err } - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceSplitterConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) if err != nil { return err } @@ -327,7 +327,7 @@ func resourceConsulServiceSplitterConfigEntryDelete(d *schema.ResourceData, meta return nil } -func makeServiceDefaultsConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { +func makeServiceSplitterConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { configMap["kind"] = kind configMap["name"] = name configMap["Namespace"] = namespace From fb0ba93e80cb2f4b09129837f98d13c850ed60ff Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 07:35:57 +0530 Subject: [PATCH 14/89] added test files --- .../resource_consul_service_splitter_config_entry_ce_test.go | 3 +++ .../resource_consul_service_splitter_config_entry_ee_test.go | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 consul/resource_consul_service_splitter_config_entry_ce_test.go create mode 100644 consul/resource_consul_service_splitter_config_entry_ee_test.go diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go new file mode 100644 index 00000000..ed4e0219 --- /dev/null +++ b/consul/resource_consul_service_splitter_config_entry_ce_test.go @@ -0,0 +1,3 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go new file mode 100644 index 00000000..57db0693 --- /dev/null +++ b/consul/resource_consul_service_splitter_config_entry_ee_test.go @@ -0,0 +1,2 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 \ No newline at end of file From 40c285a7db2aaa8b38896017b66148e4b58d466a Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 09:18:53 +0530 Subject: [PATCH 15/89] comments addressed --- .../resource_service_defaults_config_entry.go | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go index db44c244..04241bad 100644 --- a/consul/resource_service_defaults_config_entry.go +++ b/consul/resource_service_defaults_config_entry.go @@ -13,6 +13,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) +const Kind = "service-defaults" + var upstreamConfigSchema = &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -367,15 +369,6 @@ func resourceServiceDefaultsConfigEntry() *schema.Resource { } } -func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.QueryOptions) { - // exported-services config entries are weird in that their name correspond - // to the partition they are created in, see - // https://www.consul.io/docs/connect/config-entries/exported-services#configuration-parameters - if kind == "exported-services" && name != "default" { - qOpts.Partition = name - } -} - func formatKey(key string) string { tokens := strings.Split(key, "_") keyToReturn := "" @@ -466,7 +459,7 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta name := d.Get("name").(string) configMap := make(map[string]interface{}) - configMap["kind"] = "service-defaults" + configMap["kind"] = Kind configMap["name"] = name @@ -477,8 +470,6 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta return err } - fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) - var attributes []string for key, _ := range serviceDefaultsConfigEntrySchema { @@ -494,7 +485,7 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta return err } - configEntry, err := makeServiceDefaultsConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceDefaultsConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) if err != nil { return err } @@ -542,8 +533,8 @@ func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta return nil } -func makeServiceDefaultsConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { - configMap["kind"] = kind +func makeServiceDefaultsConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { + configMap["kind"] = Kind configMap["name"] = name configMap["Namespace"] = namespace configMap["Partition"] = partition From eba61e390f86550c5460e723716762005a3677fd Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 13:48:04 +0530 Subject: [PATCH 16/89] fix typo --- consul/resource_service_defaults_config_entry_ce_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_service_defaults_config_entry_ce_test.go b/consul/resource_service_defaults_config_entry_ce_test.go index c5f3d44f..ccde80cc 100644 --- a/consul/resource_service_defaults_config_entry_ce_test.go +++ b/consul/resource_service_defaults_config_entry_ce_test.go @@ -139,7 +139,7 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { }) } -// Destination and Upstream Config are exlusive. +// Destination and Upstream Config are exclusive. const testConsulServiceDefaultsConfigEntryWithDestination = ` resource "consul_service_defaults_config_entry" "foo" { name = "service-defaults-test-1" From 282c9ad651735b6cf3656534e006357810f8bdb5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 14:02:51 +0530 Subject: [PATCH 17/89] service splitter --- consul/helper.go | 94 ++++ ...ce_consul_service_splitter_config_entry.go | 104 +--- ...l_service_splitter_config_entry_ce_test.go | 48 ++ ...l_service_splitter_config_entry_ee_test.go | 45 +- consul/resource_provider.go | 1 + .../resource_service_defaults_config_entry.go | 463 ++++++++++++++++++ ...e_service_defaults_config_entry_ce_test.go | 310 ++++++++++++ ...e_service_defaults_config_entry_ee_test.go | 318 ++++++++++++ 8 files changed, 1285 insertions(+), 98 deletions(-) create mode 100644 consul/helper.go create mode 100644 consul/resource_service_defaults_config_entry.go create mode 100644 consul/resource_service_defaults_config_entry_ce_test.go create mode 100644 consul/resource_service_defaults_config_entry_ee_test.go diff --git a/consul/helper.go b/consul/helper.go new file mode 100644 index 00000000..f36a67d0 --- /dev/null +++ b/consul/helper.go @@ -0,0 +1,94 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "encoding/json" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "reflect" + "strings" +) + +func isSlice(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array +} + +func isMap(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Map +} + +func isSetSchema(v interface{}) bool { + return reflect.TypeOf(v).String() == "*schema.Set" +} + +func isStruct(v interface{}) bool { + return reflect.TypeOf(v).Kind() == reflect.Struct +} + +func formatKey(key string) string { + tokens := strings.Split(key, "_") + keyToReturn := "" + for _, token := range tokens { + if token == "tls" { + keyToReturn += strings.ToUpper(token) + } else { + keyToReturn += strings.ToTitle(token) + } + } + return keyToReturn +} + +func FormatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { + if isMap(config) { + formattedMap := make(map[string]interface{}) + for key, value := range config.(map[string]interface{}) { + formattedKey := formatFunc(key) + formattedValue, err := FormatKeys(value, formatKey) + if err != nil { + return nil, err + } + if formattedValue != nil { + formattedMap[formattedKey] = formattedValue + } + } + return formattedMap, nil + } else if isSlice(config) { + var newSlice []interface{} + listValue := config.([]interface{}) + for _, elem := range listValue { + newElem, err := FormatKeys(elem, formatKey) + if err != nil { + return nil, err + } + newSlice = append(newSlice, newElem) + } + return newSlice, nil + } else if isStruct(config) { + var modifiedStruct map[string]interface{} + jsonValue, err := json.Marshal(config) + if err != nil { + return nil, err + } + err = json.Unmarshal(jsonValue, &modifiedStruct) + if err != nil { + return nil, err + } + formattedStructKeys, err := FormatKeys(modifiedStruct, formatKey) + if err != nil { + return nil, err + } + return formattedStructKeys, nil + } else if isSetSchema(config) { + valueList := config.(*schema.Set).List() + if len(valueList) > 0 { + formattedSetValue, err := FormatKeys(valueList[0], formatKey) + if err != nil { + return nil, err + } + return formattedSetValue, nil + } + return nil, nil + } + return config, nil +} diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go index 004416c6..e242e636 100644 --- a/consul/resource_consul_service_splitter_config_entry.go +++ b/consul/resource_consul_service_splitter_config_entry.go @@ -4,15 +4,15 @@ package consul import ( - "encoding/json" "fmt" - "reflect" "strings" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) +const KindServiceSplitter = "service-splitter" + var serviceSplitterConfigEntrySchema = map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -156,94 +156,6 @@ func resourceServiceSplitterConfigEntry() *schema.Resource { } } -func fixQOptsForServiceDefaultsConfigEntry(name, kind string, qOpts *consulapi.QueryOptions) { - // exported-services config entries are weird in that their name correspond - // to the partition they are created in, see - // https://www.consul.io/docs/connect/config-entries/exported-services#configuration-parameters - if kind == "exported-services" && name != "default" { - qOpts.Partition = name - } -} - -func formatKey(key string) string { - tokens := strings.Split(key, "_") - keyToReturn := "" - for _, token := range tokens { - keyToReturn += strings.ToTitle(token) - } - return keyToReturn -} - -func isSlice(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array -} - -func isMap(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Map -} - -func isSetSchema(v interface{}) bool { - return reflect.TypeOf(v).String() == "*schema.Set" -} - -func isStruct(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Struct -} - -func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { - if isMap(config) { - formattedMap := make(map[string]interface{}) - for key, value := range config.(map[string]interface{}) { - formattedKey := formatFunc(key) - formattedValue, err := formatKeys(value, formatKey) - if err != nil { - return nil, err - } - if formattedValue != nil { - formattedMap[formattedKey] = formattedValue - } - } - return formattedMap, nil - } else if isSlice(config) { - var newSlice []interface{} - listValue := config.([]interface{}) - for _, elem := range listValue { - newElem, err := formatKeys(elem, formatKey) - if err != nil { - return nil, err - } - newSlice = append(newSlice, newElem) - } - return newSlice, nil - } else if isStruct(config) { - var modifiedStruct map[string]interface{} - jsonValue, err := json.Marshal(config) - if err != nil { - return nil, err - } - err = json.Unmarshal(jsonValue, &modifiedStruct) - if err != nil { - return nil, err - } - formattedStructKeys, err := formatKeys(modifiedStruct, formatKey) - if err != nil { - return nil, err - } - return formattedStructKeys, nil - } else if isSetSchema(config) { - valueList := config.(*schema.Set).List() - if len(valueList) > 0 { - formattedSetValue, err := formatKeys(valueList[0], formatKey) - if err != nil { - return nil, err - } - return formattedSetValue, nil - } - return nil, nil - } - return config, nil -} - func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { client, qOpts, wOpts := getClient(d, meta) configEntries := client.ConfigEntries() @@ -251,7 +163,7 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta name := d.Get("name").(string) configMap := make(map[string]interface{}) - configMap["kind"] = "service-splitter" + configMap["kind"] = KindServiceSplitter configMap["name"] = name @@ -262,8 +174,6 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta return err } - fixQOptsForServiceDefaultsConfigEntry(name, kind, qOpts) - var attributes []string for key, _ := range serviceSplitterConfigEntrySchema { @@ -274,12 +184,12 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta configMap[attribute] = d.Get(attribute) } - formattedMap, err := formatKeys(configMap, formatKey) + formattedMap, err := FormatKeys(configMap, formatKey) if err != nil { return err } - configEntry, err := makeServiceSplitterConfigEntry(kind, name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceSplitterConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) if err != nil { return err } @@ -327,8 +237,8 @@ func resourceConsulServiceSplitterConfigEntryDelete(d *schema.ResourceData, meta return nil } -func makeServiceSplitterConfigEntry(kind, name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { - configMap["kind"] = kind +func makeServiceSplitterConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { + configMap["kind"] = KindServiceSplitter configMap["name"] = name configMap["Namespace"] = namespace configMap["Partition"] = partition diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go index ed4e0219..5a67fe7f 100644 --- a/consul/resource_consul_service_splitter_config_entry_ce_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ce_test.go @@ -1,3 +1,51 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulServiceSplitterConfigEntryCE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "service-splitter"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), + ), + }, + }, + }) +} + +const testConsulServiceSplitterConfigEntryCE = ` +resource "consul_service_splitter_config_entry" "foo" { + name = "web" + meta = { + key = "value" + } + splits { + weight = 90 + service_subset = "v1" + service = "web" + } + splits { + weight = 10 + service = "web" + service_subset = "v2" + } +} +` diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go index 57db0693..794cda1f 100644 --- a/consul/resource_consul_service_splitter_config_entry_ee_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ee_test.go @@ -1,2 +1,45 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 \ No newline at end of file +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulServiceSplitterConfigEntryEE, + Check: resource.ComposeTestCheckFunc(), + }, + }, + }) +} + +const testConsulServiceSplitterConfigEntryEE = ` +resource "consul_service_splitter_config_entry" "service-splitter-config-entry" { + name = "service-splitter" + meta = { + key = "value" + } + namespace = "namespace" + partition = "partition" + splits { + weight = 90 + service = "frontend" + service_subset = "v1" + } + splits { + weight = 10 + service = "frontend" + service_subset = "v2" + } +} +` diff --git a/consul/resource_provider.go b/consul/resource_provider.go index d7604f33..d3b982fe 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -251,6 +251,7 @@ func Provider() terraform.ResourceProvider { "consul_network_area": resourceConsulNetworkArea(), "consul_peering_token": resourceSourceConsulPeeringToken(), "consul_peering": resourceSourceConsulPeering(), + "consul_service_defaults_config_entry": resourceServiceDefaultsConfigEntry(), "consul_service_splitter_config_entry": resourceServiceSplitterConfigEntry(), }, diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_service_defaults_config_entry.go new file mode 100644 index 00000000..de913dd1 --- /dev/null +++ b/consul/resource_service_defaults_config_entry.go @@ -0,0 +1,463 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +const KindServiceDefaults = "service-defaults" + +var upstreamConfigSchema = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_listener_json": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_cluster_json": { + Type: schema.TypeString, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + }, + "connect_timeout_ms": { + Type: schema.TypeString, + Optional: true, + }, + "limits": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "passive_health_check": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeInt, + Optional: true, + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + }, + "base_ejection_time": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "balance_outbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + }, +} + +var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ + "kind": { + Type: schema.TypeString, + Required: false, + ForceNew: true, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The partition the config entry is associated with.", + }, + + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + }, + + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + + "mode": { + Type: schema.TypeString, + Optional: true, + }, + + "upstream_config": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "overrides": { + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchema, + }, + "defaults": { + Type: schema.TypeSet, + Optional: true, + Elem: upstreamConfigSchema, + }, + }, + }, + }, + + "transparent_proxy": { + Type: schema.TypeSet, + Optional: true, + 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, + }, + + "envoy_extensions": { + Type: schema.TypeList, + Optional: true, + 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, + 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, + }, + + "max_inbound_connections": { + Type: schema.TypeInt, + Optional: true, + }, + + "local_request_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Required: true, + Type: schema.TypeString, + }, + }, + }, + }, + + "external_sni": { + Type: schema.TypeString, + Optional: true, + }, + + "expose": { + Type: schema.TypeSet, + Required: true, + 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 resourceServiceDefaultsConfigEntry() *schema.Resource { + + return &schema.Resource{ + Create: resourceConsulServiceDefaultsConfigEntryUpdate, + Update: resourceConsulServiceDefaultsConfigEntryUpdate, + Read: resourceConsulServiceDefaultsConfigEntryRead, + Delete: resourceConsulServiceDefaultsConfigEntryDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + var kind, name, partition, namespace string + switch len(parts) { + case 2: + kind = parts[0] + name = parts[1] + case 4: + partition = parts[0] + namespace = parts[1] + kind = parts[2] + name = parts[3] + default: + return nil, fmt.Errorf(`expected path of the form "/" or "///"`) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + sw := newStateWriter(d) + sw.set("kind", kind) + sw.set("name", name) + sw.set("partition", partition) + sw.set("namespace", namespace) + + err := sw.error() + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil + }, + }, + Schema: serviceDefaultsConfigEntrySchema, + } +} + +func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { + client, qOpts, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + + name := d.Get("name").(string) + + configMap := make(map[string]interface{}) + configMap["kind"] = KindServiceDefaults + + configMap["name"] = name + + kind := configMap["kind"].(string) + err := d.Set("kind", kind) + + if err != nil { + return err + } + + var attributes []string + + for key, _ := range serviceDefaultsConfigEntrySchema { + attributes = append(attributes, key) + } + + for _, attribute := range attributes { + configMap[attribute] = d.Get(attribute) + } + + formattedMap, err := FormatKeys(configMap, formatKey) + if err != nil { + return err + } + + configEntry, err := makeServiceDefaultsConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + if err != nil { + return err + } + + if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { + return fmt.Errorf("failed to set '%s' config entry: %v", name, err) + } + _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + return fmt.Errorf(`failed to read config entry after setting it. +This may happen when some attributes have an unexpected value. +Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html +to see what values are expected`, configEntry.GetKind()) + } + return fmt.Errorf("failed to read config entry: %v", err) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + return resourceConsulServiceDefaultsConfigEntryRead(d, meta) +} + +func resourceConsulServiceDefaultsConfigEntryRead(d *schema.ResourceData, meta interface{}) error { + client, qOpts, _ := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + fixQOptsForConfigEntry(configName, configKind, qOpts) + + _, _, err := configEntries.Get(configKind, configName, qOpts) + return err +} + +func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { + client, _, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { + return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) + } + d.SetId("") + return nil +} + +func makeServiceDefaultsConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { + configMap["kind"] = KindServiceDefaults + configMap["name"] = name + configMap["Namespace"] = namespace + configMap["Partition"] = partition + + configEntry, err := consulapi.DecodeConfigEntry(configMap) + if err != nil { + return nil, fmt.Errorf("failed to decode config entry: %v", err) + } + + return configEntry, nil +} diff --git a/consul/resource_service_defaults_config_entry_ce_test.go b/consul/resource_service_defaults_config_entry_ce_test.go new file mode 100644 index 00000000..c5f3d44f --- /dev/null +++ b/consul/resource_service_defaults_config_entry_ce_test.go @@ -0,0 +1,310 @@ +// 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_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfig, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exlusive. +const testConsulServiceDefaultsConfigEntryWithDestination = ` +resource "consul_service_defaults_config_entry" "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_service_defaults_config_entry" "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 = 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_service_defaults_config_entry_ee_test.go b/consul/resource_service_defaults_config_entry_ee_test.go new file mode 100644 index 00000000..1b27dfe1 --- /dev/null +++ b/consul/resource_service_defaults_config_entry_ee_test.go @@ -0,0 +1,318 @@ +// 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_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfigEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exlusive. +const testConsulServiceDefaultsConfigEntryWithDestinationEE = ` +resource "consul_service_defaults_config_entry" "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_service_defaults_config_entry" "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" + } + } +} +` From bfb32f13f9a4843886d25bcab185330fea7a0933 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 14:09:06 +0530 Subject: [PATCH 18/89] fix force new --- consul/resource_consul_service_splitter_config_entry.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go index e242e636..33540ae9 100644 --- a/consul/resource_consul_service_splitter_config_entry.go +++ b/consul/resource_consul_service_splitter_config_entry.go @@ -16,7 +16,8 @@ const KindServiceSplitter = "service-splitter" var serviceSplitterConfigEntrySchema = map[string]*schema.Schema{ "name": { Type: schema.TypeString, - Optional: true, + Required: true, + ForceNew: true, }, "kind": { Type: schema.TypeString, @@ -27,10 +28,12 @@ var serviceSplitterConfigEntrySchema = map[string]*schema.Schema{ "partition": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, "namespace": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, "meta": { Type: schema.TypeMap, From f8ed7ef70ba59af6f607e00cb5beb67e04193cbe Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 14:30:43 +0530 Subject: [PATCH 19/89] added tests for service splitter --- ...l_service_splitter_config_entry_ce_test.go | 38 ++++++++++- ...l_service_splitter_config_entry_ee_test.go | 64 +++++++++++++++---- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go index 5a67fe7f..80c6ec3e 100644 --- a/consul/resource_consul_service_splitter_config_entry_ce_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ce_test.go @@ -18,13 +18,15 @@ func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { { Config: testConsulServiceSplitterConfigEntryCE, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "service-splitter"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "web"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "meta.key", "value"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.#", "2"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), ), }, }, @@ -32,9 +34,39 @@ func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { } const testConsulServiceSplitterConfigEntryCE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Protocol = "http" + Expose = {} + MeshGateway = {} + TransparentProxy = {} + }) +} + +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + resource "consul_service_splitter_config_entry" "foo" { - name = "web" - meta = { + name = consul_config_entry.service_resolver.name + meta = { key = "value" } splits { diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go index 794cda1f..980a22e8 100644 --- a/consul/resource_consul_service_splitter_config_entry_ee_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ee_test.go @@ -16,29 +16,71 @@ func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { Providers: providers, Steps: []resource.TestStep{ { - Config: testConsulServiceSplitterConfigEntryEE, - Check: resource.ComposeTestCheckFunc(), + Config: testConsulServiceSplitterConfigEntryCE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "namespace", "ns"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "partition", "pt"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), + ), }, }, }) } const testConsulServiceSplitterConfigEntryEE = ` -resource "consul_service_splitter_config_entry" "service-splitter-config-entry" { - name = "service-splitter" - meta = { +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Protocol = "http" + Expose = {} + MeshGateway = {} + TransparentProxy = {} + }) +} + +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + +resource "consul_service_splitter_config_entry" "foo" { + name = consul_config_entry.service_resolver.name + namespace = "ns" + partition = "pt" + meta = { key = "value" } - namespace = "namespace" - partition = "partition" splits { - weight = 90 - service = "frontend" + weight = 90 service_subset = "v1" + service = "web" } splits { - weight = 10 - service = "frontend" + weight = 10 + service = "web" service_subset = "v2" } } From 74c2353213c6fd45cd0f5e7af8a302710e98bc95 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 15:12:00 +0530 Subject: [PATCH 20/89] update tests --- ...l_service_splitter_config_entry_ce_test.go | 24 +++++++++++++++++ ...l_service_splitter_config_entry_ee_test.go | 26 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go index 80c6ec3e..c28a450b 100644 --- a/consul/resource_consul_service_splitter_config_entry_ce_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ce_test.go @@ -24,9 +24,13 @@ func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.request_headers.810692046.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.response_headers.3374032271.set.x-web-version", "to-v1"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.request_headers.585597472.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.response_headers.3685616225.set.x-web-version", "to-v2"), ), }, }, @@ -73,11 +77,31 @@ resource "consul_service_splitter_config_entry" "foo" { weight = 90 service_subset = "v1" service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } } splits { weight = 10 service = "web" service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } } } ` diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go index 980a22e8..c84300cf 100644 --- a/consul/resource_consul_service_splitter_config_entry_ee_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ee_test.go @@ -16,7 +16,7 @@ func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { Providers: providers, Steps: []resource.TestStep{ { - Config: testConsulServiceSplitterConfigEntryCE, + Config: testConsulServiceSplitterConfigEntryEE, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "web"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "namespace", "ns"), @@ -26,9 +26,13 @@ func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.request_headers.810692046.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.response_headers.3374032271.set.x-web-version", "to-v1"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.request_headers.585597472.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.response_headers.3685616225.set.x-web-version", "to-v2"), ), }, }, @@ -77,11 +81,31 @@ resource "consul_service_splitter_config_entry" "foo" { weight = 90 service_subset = "v1" service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } } splits { weight = 10 service = "web" service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } } } ` From b98982aba0c78684d5416b0faef1c41687f318f4 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 16:53:56 +0530 Subject: [PATCH 21/89] rename files --- ..._entry.go => resource_consul_service_defaults_config_entry.go} | 0 ...o => resource_consul_service_defaults_config_entry_ce_test.go} | 0 ...o => resource_consul_service_defaults_config_entry_ee_test.go} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename consul/{resource_service_defaults_config_entry.go => resource_consul_service_defaults_config_entry.go} (100%) rename consul/{resource_service_defaults_config_entry_ce_test.go => resource_consul_service_defaults_config_entry_ce_test.go} (100%) rename consul/{resource_service_defaults_config_entry_ee_test.go => resource_consul_service_defaults_config_entry_ee_test.go} (100%) diff --git a/consul/resource_service_defaults_config_entry.go b/consul/resource_consul_service_defaults_config_entry.go similarity index 100% rename from consul/resource_service_defaults_config_entry.go rename to consul/resource_consul_service_defaults_config_entry.go diff --git a/consul/resource_service_defaults_config_entry_ce_test.go b/consul/resource_consul_service_defaults_config_entry_ce_test.go similarity index 100% rename from consul/resource_service_defaults_config_entry_ce_test.go rename to consul/resource_consul_service_defaults_config_entry_ce_test.go diff --git a/consul/resource_service_defaults_config_entry_ee_test.go b/consul/resource_consul_service_defaults_config_entry_ee_test.go similarity index 100% rename from consul/resource_service_defaults_config_entry_ee_test.go rename to consul/resource_consul_service_defaults_config_entry_ee_test.go From 444c9965a41b7dbdf68eb42204efd330ed117c7a Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 17:26:14 +0530 Subject: [PATCH 22/89] init --- ...ce_consul_service_resolver_config_entry.go | 238 ++++++++++++++++++ consul/resource_provider.go | 1 + 2 files changed, 239 insertions(+) create mode 100644 consul/resource_consul_service_resolver_config_entry.go diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go new file mode 100644 index 00000000..3f0e14c3 --- /dev/null +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -0,0 +1,238 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +const KindServiceResolver = "service-resolver" + +var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "kind": { + Type: schema.TypeString, + Required: false, + ForceNew: true, + Computed: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "subsets": { + Type: schema.TypeMap, + Required: true, + Elem: &schema.Schema{Type: schema.TypeMap, + Required: true, + Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + "filter": { + Type: schema.TypeString, + Required: true, + }, + "only_passing": { + Type: schema.TypeBool, + Required: true, + }, + }}, + }, + }, + "default_subset": { + Type: schema.TypeString, + Optional: true, + }, + "redirect": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Optional: true, + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "sameness_group": { + Type: schema.TypeString, + Optional: true, + }, + "datacenter": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, +} + +func resourceServiceResolverConfigEntry() *schema.Resource { + + return &schema.Resource{ + Create: resourceConsulServiceResolverConfigEntryUpdate, + Update: resourceConsulServiceResolverConfigEntryUpdate, + Read: resourceConsulServiceResolverConfigEntryRead, + Delete: resourceConsulServiceResolverConfigEntryDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + var kind, name, partition, namespace string + switch len(parts) { + case 2: + kind = parts[0] + name = parts[1] + case 4: + partition = parts[0] + namespace = parts[1] + kind = parts[2] + name = parts[3] + default: + return nil, fmt.Errorf(`expected path of the form "/" or "///"`) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + sw := newStateWriter(d) + sw.set("kind", kind) + sw.set("name", name) + sw.set("partition", partition) + sw.set("namespace", namespace) + + err := sw.error() + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil + }, + }, + Schema: serviceResolverConfigEntrySchema, + } +} + +func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { + client, qOpts, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + + name := d.Get("name").(string) + + configMap := make(map[string]interface{}) + configMap["kind"] = KindServiceResolver + + configMap["name"] = name + + kind := configMap["kind"].(string) + err := d.Set("kind", kind) + + if err != nil { + return err + } + + var attributes []string + + for key, _ := range serviceSplitterConfigEntrySchema { + attributes = append(attributes, key) + } + + for _, attribute := range attributes { + configMap[attribute] = d.Get(attribute) + } + + formattedMap, err := FormatKeys(configMap, formatKey) + if err != nil { + return err + } + + configEntry, err := makeServiceResolverConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + if err != nil { + return err + } + + if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { + return fmt.Errorf("failed to set '%s' config entry: %v", name, err) + } + _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + return fmt.Errorf(`failed to read config entry after setting it. +This may happen when some attributes have an unexpected value. +Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html +to see what values are expected`, configEntry.GetKind()) + } + return fmt.Errorf("failed to read config entry: %v", err) + } + + d.SetId(fmt.Sprintf("%s-%s", kind, name)) + return resourceConsulServiceSplitterConfigEntryRead(d, meta) +} + +func resourceConsulServiceResolverConfigEntryRead(d *schema.ResourceData, meta interface{}) error { + client, qOpts, _ := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + fixQOptsForConfigEntry(configName, configKind, qOpts) + + _, _, err := configEntries.Get(configKind, configName, qOpts) + return err +} + +func resourceConsulServiceResolverConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { + client, _, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() + configKind := d.Get("kind").(string) + configName := d.Get("name").(string) + + if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { + return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) + } + d.SetId("") + return nil +} + +func makeServiceResolverConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { + configMap["kind"] = KindServiceResolver + configMap["name"] = name + configMap["Namespace"] = namespace + configMap["Partition"] = partition + + configEntry, err := consulapi.DecodeConfigEntry(configMap) + if err != nil { + return nil, fmt.Errorf("failed to decode config entry: %v", err) + } + + return configEntry, nil +} diff --git a/consul/resource_provider.go b/consul/resource_provider.go index d3b982fe..98e23f82 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -253,6 +253,7 @@ func Provider() terraform.ResourceProvider { "consul_peering": resourceSourceConsulPeering(), "consul_service_defaults_config_entry": resourceServiceDefaultsConfigEntry(), "consul_service_splitter_config_entry": resourceServiceSplitterConfigEntry(), + "consul_service_resolver_config_entry": resourceServiceResolverConfigEntry(), }, ConfigureFunc: providerConfigure, From e265a5e69db31d59af9df6ac83b7b834747f1fb4 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 17:29:15 +0530 Subject: [PATCH 23/89] made the function private --- consul/helper.go | 10 +++++----- .../resource_consul_service_defaults_config_entry.go | 2 +- .../resource_consul_service_splitter_config_entry.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/consul/helper.go b/consul/helper.go index f36a67d0..2efb91b0 100644 --- a/consul/helper.go +++ b/consul/helper.go @@ -39,12 +39,12 @@ func formatKey(key string) string { return keyToReturn } -func FormatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { +func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { if isMap(config) { formattedMap := make(map[string]interface{}) for key, value := range config.(map[string]interface{}) { formattedKey := formatFunc(key) - formattedValue, err := FormatKeys(value, formatKey) + formattedValue, err := formatKeys(value, formatKey) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func FormatKeys(config interface{}, formatFunc func(string) string) (interface{} var newSlice []interface{} listValue := config.([]interface{}) for _, elem := range listValue { - newElem, err := FormatKeys(elem, formatKey) + newElem, err := formatKeys(elem, formatKey) if err != nil { return nil, err } @@ -74,7 +74,7 @@ func FormatKeys(config interface{}, formatFunc func(string) string) (interface{} if err != nil { return nil, err } - formattedStructKeys, err := FormatKeys(modifiedStruct, formatKey) + formattedStructKeys, err := formatKeys(modifiedStruct, formatKey) if err != nil { return nil, err } @@ -82,7 +82,7 @@ func FormatKeys(config interface{}, formatFunc func(string) string) (interface{} } else if isSetSchema(config) { valueList := config.(*schema.Set).List() if len(valueList) > 0 { - formattedSetValue, err := FormatKeys(valueList[0], formatKey) + formattedSetValue, err := formatKeys(valueList[0], formatKey) if err != nil { return nil, err } diff --git a/consul/resource_consul_service_defaults_config_entry.go b/consul/resource_consul_service_defaults_config_entry.go index df769cfc..a81dfa62 100644 --- a/consul/resource_consul_service_defaults_config_entry.go +++ b/consul/resource_consul_service_defaults_config_entry.go @@ -396,7 +396,7 @@ func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta configMap[attribute] = d.Get(attribute) } - formattedMap, err := FormatKeys(configMap, formatKey) + formattedMap, err := formatKeys(configMap, formatKey) if err != nil { return err diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go index 33540ae9..b2200d05 100644 --- a/consul/resource_consul_service_splitter_config_entry.go +++ b/consul/resource_consul_service_splitter_config_entry.go @@ -187,7 +187,7 @@ func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta configMap[attribute] = d.Get(attribute) } - formattedMap, err := FormatKeys(configMap, formatKey) + formattedMap, err := formatKeys(configMap, formatKey) if err != nil { return err } From 7943cacf38fa4e3d55e6669b63015c5845c8b7cf Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 18:54:59 +0530 Subject: [PATCH 24/89] added helper test --- consul/helper.go | 21 ++++----------------- consul/helper_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ go.mod | 5 ++++- go.sum | 2 ++ 4 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 consul/helper_test.go diff --git a/consul/helper.go b/consul/helper.go index 2efb91b0..32628092 100644 --- a/consul/helper.go +++ b/consul/helper.go @@ -4,8 +4,9 @@ package consul import ( - "encoding/json" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "golang.org/x/text/cases" + "golang.org/x/text/language" "reflect" "strings" ) @@ -33,7 +34,8 @@ func formatKey(key string) string { if token == "tls" { keyToReturn += strings.ToUpper(token) } else { - keyToReturn += strings.ToTitle(token) + caser := cases.Title(language.English) + keyToReturn += caser.String(token) } } return keyToReturn @@ -64,21 +66,6 @@ func formatKeys(config interface{}, formatFunc func(string) string) (interface{} newSlice = append(newSlice, newElem) } return newSlice, nil - } else if isStruct(config) { - var modifiedStruct map[string]interface{} - jsonValue, err := json.Marshal(config) - if err != nil { - return nil, err - } - err = json.Unmarshal(jsonValue, &modifiedStruct) - if err != nil { - return nil, err - } - formattedStructKeys, err := formatKeys(modifiedStruct, formatKey) - if err != nil { - return nil, err - } - return formattedStructKeys, nil } else if isSetSchema(config) { valueList := config.(*schema.Set).List() if len(valueList) > 0 { diff --git a/consul/helper_test.go b/consul/helper_test.go new file mode 100644 index 00000000..92705df8 --- /dev/null +++ b/consul/helper_test.go @@ -0,0 +1,41 @@ +package consul + +import ( + "bytes" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/stretchr/testify/require" + "testing" +) + +func TestFormatKeysFunc(t *testing.T) { + dummySetSchema := new(schema.Set) + dummySetSchema.F = func(i interface{}) int { + var buf bytes.Buffer + buf.WriteString(fmt.Sprintf("%s-", i)) + return hashcode.String(buf.String()) + } + dummySetSchema.Add(map[string]interface{}{"test_set_key": "test_value"}) + dataSet := []map[string]interface{}{ + { + "input": map[string]interface{}{ + "test_key": "value1", + "test_tls_key": "value2", + }, + "expected": map[string]interface{}{ + "TestKey": "value1", + "TestTLSKey": "value2", + }, + }, + { + "input": dummySetSchema, + "expected": map[string]interface{}{"TestSetKey": "test_value"}, + }, + } + for _, testCase := range dataSet { + res, err := formatKeys(testCase["input"], formatKey) + require.NoError(t, err) + require.Equal(t, testCase["expected"], res) + } +} diff --git a/go.mod b/go.mod index df391ba3..b27e07c9 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 github.com/hashicorp/terraform-plugin-sdk v1.17.2 github.com/mitchellh/mapstructure v1.5.0 + github.com/stretchr/testify v1.8.3 ) require ( @@ -12,7 +13,9 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v0.12.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( @@ -91,7 +94,7 @@ require ( golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/text v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.114.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index f704096c..093d0fe6 100644 --- a/go.sum +++ b/go.sum @@ -601,6 +601,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= @@ -652,6 +653,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= From 1e5a15c137ba6f01db6eb83918cddd8725360dbe Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 26 Sep 2023 18:55:28 +0530 Subject: [PATCH 25/89] removed is struct method --- consul/helper.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/consul/helper.go b/consul/helper.go index 32628092..3735003b 100644 --- a/consul/helper.go +++ b/consul/helper.go @@ -23,10 +23,6 @@ func isSetSchema(v interface{}) bool { return reflect.TypeOf(v).String() == "*schema.Set" } -func isStruct(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Struct -} - func formatKey(key string) string { tokens := strings.Split(key, "_") keyToReturn := "" From 07d240994afcf12c1954a0aa8597f3ad9b715307 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 27 Sep 2023 10:22:18 +0530 Subject: [PATCH 26/89] fix func name --- consul/resource_consul_service_resolver_config_entry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 3f0e14c3..55e2311d 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -170,7 +170,7 @@ func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta configMap[attribute] = d.Get(attribute) } - formattedMap, err := FormatKeys(configMap, formatKey) + formattedMap, err := formatKeys(configMap, formatKey) if err != nil { return err } From 7ea84d58cc7dc3f536b5f3125420d1fc118f9b0e Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 27 Sep 2023 11:03:15 +0530 Subject: [PATCH 27/89] init --- consul/helper.go | 2 +- consul/helper_test.go | 2 + ...ce_consul_service_resolver_config_entry.go | 156 +++++++++++++++++- 3 files changed, 158 insertions(+), 2 deletions(-) diff --git a/consul/helper.go b/consul/helper.go index 3735003b..03179ebe 100644 --- a/consul/helper.go +++ b/consul/helper.go @@ -27,7 +27,7 @@ func formatKey(key string) string { tokens := strings.Split(key, "_") keyToReturn := "" for _, token := range tokens { - if token == "tls" { + if token == "tls" || token == "ttl" { keyToReturn += strings.ToUpper(token) } else { caser := cases.Title(language.English) diff --git a/consul/helper_test.go b/consul/helper_test.go index 92705df8..ce2197b1 100644 --- a/consul/helper_test.go +++ b/consul/helper_test.go @@ -22,10 +22,12 @@ func TestFormatKeysFunc(t *testing.T) { "input": map[string]interface{}{ "test_key": "value1", "test_tls_key": "value2", + "ttl": "value3", }, "expected": map[string]interface{}{ "TestKey": "value1", "TestTLSKey": "value2", + "TTL": "value3", }, }, { diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 55e2311d..4cc498c7 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -40,10 +40,19 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "connect_timeout": { + Type: schema.TypeString, + Optional: true, + }, + "request_timeout": { + Type: schema.TypeString, + Optional: true, + }, "subsets": { Type: schema.TypeMap, Required: true, - Elem: &schema.Schema{Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeMap, Required: true, Elem: &schema.Resource{Schema: map[string]*schema.Schema{ "filter": { @@ -97,6 +106,151 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ }, }, }, + "failover": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Optional: true, + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "sameness_group": { + Type: schema.TypeString, + Optional: true, + }, + "datacenters": { + Type: schema.TypeList, + Optional: true, + Elem: schema.TypeString, + }, + "targets": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Optional: true, + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "datacenter": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "load_balancer": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy": { + Type: schema.TypeString, + Optional: true, + }, + "least_request_config": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "choice_count": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "ring_hash_config": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "minimum_ring_size": { + Type: schema.TypeInt, + Optional: true, + }, + "maximum_ring_size": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "hash_policies": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field": { + Type: schema.TypeString, + Optional: true, + }, + "field_value": { + Type: schema.TypeString, + Optional: true, + }, + "cookie_config": { + Type: schema.TypeString, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "session": { + Type: schema.TypeBool, + Optional: true, + }, + "ttl": { + Type: schema.TypeString, + Optional: true, + }, + "path": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "source_ip": { + Type: schema.TypeBool, + Optional: true, + }, + "terminal": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + }, + }, + }, } func resourceServiceResolverConfigEntry() *schema.Resource { From 9dac561dc3c83b9df01fb3dd9d32e7742c322bf9 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 27 Sep 2023 14:47:11 +0530 Subject: [PATCH 28/89] fixes while testing --- consul/helper.go | 8 +- consul/helper_test.go | 2 + ...ce_consul_service_resolver_config_entry.go | 78 ++++++++++++++----- 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/consul/helper.go b/consul/helper.go index 03179ebe..5b63c9e1 100644 --- a/consul/helper.go +++ b/consul/helper.go @@ -12,22 +12,22 @@ import ( ) func isSlice(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array + return v != nil && (reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array) } func isMap(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Map + return v != nil && reflect.TypeOf(v).Kind() == reflect.Map } func isSetSchema(v interface{}) bool { - return reflect.TypeOf(v).String() == "*schema.Set" + return v != nil && reflect.TypeOf(v).String() == "*schema.Set" } func formatKey(key string) string { tokens := strings.Split(key, "_") keyToReturn := "" for _, token := range tokens { - if token == "tls" || token == "ttl" { + if token == "tls" || token == "ttl" || token == "ip" { keyToReturn += strings.ToUpper(token) } else { caser := cases.Title(language.English) diff --git a/consul/helper_test.go b/consul/helper_test.go index ce2197b1..7a0e4348 100644 --- a/consul/helper_test.go +++ b/consul/helper_test.go @@ -23,11 +23,13 @@ func TestFormatKeysFunc(t *testing.T) { "test_key": "value1", "test_tls_key": "value2", "ttl": "value3", + "source_ip": "value4", }, "expected": map[string]interface{}{ "TestKey": "value1", "TestTLSKey": "value2", "TTL": "value3", + "SourceIP": "value4", }, }, { diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 4cc498c7..c2b495e6 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -49,12 +49,14 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ Optional: true, }, "subsets": { - Type: schema.TypeMap, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeMap, - Required: true, - Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, "filter": { Type: schema.TypeString, Required: true, @@ -63,7 +65,7 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ Type: schema.TypeBool, Required: true, }, - }}, + }, }, }, "default_subset": { @@ -107,10 +109,14 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ }, }, "failover": { - Type: schema.TypeMap, + Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "subset_name": { + Type: schema.TypeString, + Required: true, + }, "service": { Type: schema.TypeString, Optional: true, @@ -130,7 +136,7 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ "datacenters": { Type: schema.TypeList, Optional: true, - Elem: schema.TypeString, + Elem: &schema.Schema{Type: schema.TypeString}, }, "targets": { Type: schema.TypeList, @@ -218,7 +224,7 @@ var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ Optional: true, }, "cookie_config": { - Type: schema.TypeString, + Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -316,20 +322,56 @@ func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta var attributes []string - for key, _ := range serviceSplitterConfigEntrySchema { + for key, _ := range serviceResolverConfigEntrySchema { attributes = append(attributes, key) } for _, attribute := range attributes { - configMap[attribute] = d.Get(attribute) - } - - formattedMap, err := formatKeys(configMap, formatKey) - if err != nil { - return err + if attribute == "failover" { + value := d.Get(attribute) + failover := make(map[string]interface{}) + for _, elem := range value.([]interface{}) { + valueMap := elem.(map[string]interface{}) + key := valueMap["subset_name"].(string) + delete(valueMap, "subset_name") + formattedValueMap, err := formatKeys(valueMap, formatKey) + if err != nil { + return err + } + failover[key] = formattedValueMap + } + if err != nil { + return err + } + configMap["failover"] = failover + continue + } else if attribute == "subsets" { + value := d.Get(attribute) + subsets := make(map[string]interface{}) + for _, elem := range value.([]interface{}) { + valueMap := elem.(map[string]interface{}) + key := valueMap["name"].(string) + delete(valueMap, "name") + formattedValueMap, err := formatKeys(valueMap, formatKey) + if err != nil { + return err + } + subsets[key] = formattedValueMap + } + if err != nil { + return err + } + configMap["subsets"] = subsets + continue + } + keyFormattedMap, err := formatKeys(d.Get(attribute), formatKey) + if err != nil { + return err + } + configMap[attribute] = keyFormattedMap } - configEntry, err := makeServiceResolverConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) + configEntry, err := makeServiceResolverConfigEntry(name, configMap, wOpts.Namespace, wOpts.Partition) if err != nil { return err } From 68bb034942aa87146fb41449bcf766e81597f598 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 27 Sep 2023 16:39:02 +0530 Subject: [PATCH 29/89] some fixes --- ...ce_consul_service_resolver_config_entry.go | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index c2b495e6..988bbae2 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -6,6 +6,7 @@ package consul import ( "fmt" "strings" + "time" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -344,7 +345,6 @@ func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta return err } configMap["failover"] = failover - continue } else if attribute == "subsets" { value := d.Get(attribute) subsets := make(map[string]interface{}) @@ -362,13 +362,19 @@ func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta return err } configMap["subsets"] = subsets - continue - } - keyFormattedMap, err := formatKeys(d.Get(attribute), formatKey) - if err != nil { - return err + } else if attribute == "request_timeout" || attribute == "connect_timeout" { + duration, err := time.ParseDuration(d.Get(attribute).(string)) + if err != nil { + return err + } + configMap[formatKey(attribute)] = duration + } else { + keyFormattedMap, err := formatKeys(d.Get(attribute), formatKey) + if err != nil { + return err + } + configMap[formatKey(attribute)] = keyFormattedMap } - configMap[attribute] = keyFormattedMap } configEntry, err := makeServiceResolverConfigEntry(name, configMap, wOpts.Namespace, wOpts.Partition) @@ -391,7 +397,7 @@ to see what values are expected`, configEntry.GetKind()) } d.SetId(fmt.Sprintf("%s-%s", kind, name)) - return resourceConsulServiceSplitterConfigEntryRead(d, meta) + return resourceConsulServiceResolverConfigEntryRead(d, meta) } func resourceConsulServiceResolverConfigEntryRead(d *schema.ResourceData, meta interface{}) error { @@ -400,8 +406,6 @@ func resourceConsulServiceResolverConfigEntryRead(d *schema.ResourceData, meta i configKind := d.Get("kind").(string) configName := d.Get("name").(string) - fixQOptsForConfigEntry(configName, configKind, qOpts) - _, _, err := configEntries.Get(configKind, configName, qOpts) return err } From c4e119312f44816d4c32197968f5cda2872a7131 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 27 Sep 2023 18:40:23 +0530 Subject: [PATCH 30/89] read --- ...ce_consul_service_defaults_config_entry.go | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/consul/resource_consul_service_defaults_config_entry.go b/consul/resource_consul_service_defaults_config_entry.go index a81dfa62..c47e260d 100644 --- a/consul/resource_consul_service_defaults_config_entry.go +++ b/consul/resource_consul_service_defaults_config_entry.go @@ -4,6 +4,7 @@ package consul import ( + "encoding/json" "fmt" "strings" @@ -426,14 +427,38 @@ to see what values are expected`, configEntry.GetKind()) } func resourceConsulServiceDefaultsConfigEntryRead(d *schema.ResourceData, meta interface{}) error { + var attributes []string + + for key, _ := range serviceDefaultsConfigEntrySchema { + attributes = append(attributes, key) + } + client, qOpts, _ := getClient(d, meta) configEntries := client.ConfigEntries() configKind := d.Get("kind").(string) configName := d.Get("name").(string) - fixQOptsForConfigEntry(configName, configKind, qOpts) + configEntry, _, err := configEntries.Get(configKind, configName, qOpts) + + _, _, configJSON, err := parseConfigEntry(configEntry) + if err != nil { + return fmt.Errorf("failed to parse ConfigEntry: %v", err) + } + + configJsonMap := make(map[string]interface{}) + + err = json.Unmarshal([]byte(configJSON), &configJsonMap) + if err != nil { + return err + } + + for _, attribute := range attributes { + value := configJsonMap[formatKey(attribute)] + if err = d.Set(attribute, value); err != nil { + return fmt.Errorf("failed to set attribute': %v with value %v", attribute, configJsonMap[formatKey(attribute)]) + } + } - _, _, err := configEntries.Get(configKind, configName, qOpts) return err } From 72e719d88f3072aba2a2159a05dba663b9700068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Wed, 27 Sep 2023 15:50:02 +0200 Subject: [PATCH 31/89] Add read support This patch adds a new ConfigEntryImplementation interface that can be used to implement all the concrete config entries. The ConfigEntryImplementation needs to implement a `Decode()` method to decode the config entry from the user configuration and a `Write()` to update the state during refresh. What's needed in addition to those two methods will be taken care of by `resourceFromConfigEntryImplementation()`. --- GNUmakefile | 3 +- .../resource_consul_config_entry_concrete.go | 129 +++++++++ ...ce_consul_config_entry_service_splitter.go | 256 ++++++++++++++++++ ...l_config_entry_service_splitter_ce_test.go | 109 ++++++++ ...l_config_entry_service_splitter_ee_test.go | 112 ++++++++ ...ce_consul_service_splitter_config_entry.go | 255 ----------------- ...l_service_splitter_config_entry_ce_test.go | 35 +-- ...l_service_splitter_config_entry_ee_test.go | 39 +-- consul/resource_provider.go | 18 +- consul/resource_provider_test.go | 13 +- .../config_entry_service_splitter.md | 68 +++++ .../service_defaults_config_entry.md | 209 ++++++++++++++ 12 files changed, 943 insertions(+), 303 deletions(-) create mode 100644 consul/resource_consul_config_entry_concrete.go create mode 100644 consul/resource_consul_config_entry_service_splitter.go create mode 100644 consul/resource_consul_config_entry_service_splitter_ce_test.go create mode 100644 consul/resource_consul_config_entry_service_splitter_ee_test.go delete mode 100644 consul/resource_consul_service_splitter_config_entry.go create mode 100644 docs/resources/config_entry_service_splitter.md create mode 100644 docs/resources/service_defaults_config_entry.md diff --git a/GNUmakefile b/GNUmakefile index 92f9f322..1b915db2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -22,7 +22,7 @@ test: fmtcheck xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 testacc: fmtcheck - TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 2m + TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m vet: @echo "go vet ." @@ -51,4 +51,3 @@ test-compile: go test -c $(TEST) $(TESTARGS) .PHONY: build test testacc vet fmt fmtcheck errcheck test-compile test-serv - diff --git a/consul/resource_consul_config_entry_concrete.go b/consul/resource_consul_config_entry_concrete.go new file mode 100644 index 00000000..abd1d11f --- /dev/null +++ b/consul/resource_consul_config_entry_concrete.go @@ -0,0 +1,129 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +// ConfigEntryImplementation is the common implementation for all specific +// config entries. +type ConfigEntryImplementation interface { + GetKind() string + GetDescription() string + GetSchema() map[string]*schema.Schema + Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) + Write(ce consulapi.ConfigEntry, sw *stateWriter) error +} + +func resourceFromConfigEntryImplementation(c ConfigEntryImplementation) *schema.Resource { + return &schema.Resource{ + Description: c.GetDescription(), + Schema: c.GetSchema(), + Create: configEntryImplementationWrite(c), + Update: configEntryImplementationWrite(c), + Read: configEntryImplementationRead(c), + Delete: configEntryImplementationDelete(c), + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + var name, partition, namespace string + switch len(parts) { + case 1: + name = parts[0] + case 3: + partition = parts[0] + namespace = parts[1] + name = parts[2] + default: + return nil, fmt.Errorf(`expected path of the form "" or "//"`) + } + + d.SetId(name) + sw := newStateWriter(d) + sw.set("name", name) + sw.set("partition", partition) + sw.set("namespace", namespace) + + err := sw.error() + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil + }, + }, + } +} + +func configEntryImplementationWrite(impl ConfigEntryImplementation) func(d *schema.ResourceData, meta interface{}) error { + return func(d *schema.ResourceData, meta interface{}) error { + client, qOpts, wOpts := getClient(d, meta) + + configEntry, err := impl.Decode(d) + if err != nil { + return err + } + + if _, _, err := client.ConfigEntries().Set(configEntry, wOpts); err != nil { + return fmt.Errorf("failed to set '%s' config entry: %v", configEntry.GetName(), err) + } + _, _, err = client.ConfigEntries().Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + return fmt.Errorf("failed to read config entry after setting it") + } + return fmt.Errorf("failed to read config entry: %v", err) + } + + d.SetId(configEntry.GetName()) + return configEntryImplementationRead(impl)(d, meta) + } +} + +func configEntryImplementationRead(impl ConfigEntryImplementation) func(d *schema.ResourceData, meta interface{}) error { + return func(d *schema.ResourceData, meta interface{}) error { + client, qOpts, _ := getClient(d, meta) + name := d.Get("name").(string) + + fixQOptsForConfigEntry(name, impl.GetKind(), qOpts) + + ce, _, err := client.ConfigEntries().Get(impl.GetKind(), name, qOpts) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 404") { + // The config entry has been removed + d.SetId("") + return nil + } + return fmt.Errorf("failed to fetch '%s' config entry: %v", name, err) + } + if ce == nil { + d.SetId("") + return nil + } + + sw := newStateWriter(d) + if err := impl.Write(ce, sw); err != nil { + return err + } + return sw.error() + } +} + +func configEntryImplementationDelete(impl ConfigEntryImplementation) func(d *schema.ResourceData, meta interface{}) error { + return func(d *schema.ResourceData, meta interface{}) error { + client, _, wOpts := getClient(d, meta) + name := d.Get("name").(string) + + if _, err := client.ConfigEntries().Delete(impl.GetKind(), name, wOpts); err != nil { + return fmt.Errorf("failed to delete '%s' config entry: %v", name, err) + } + d.SetId("") + return nil + } +} diff --git a/consul/resource_consul_config_entry_service_splitter.go b/consul/resource_consul_config_entry_service_splitter.go new file mode 100644 index 00000000..f30a9ad6 --- /dev/null +++ b/consul/resource_consul_config_entry_service_splitter.go @@ -0,0 +1,256 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +type serviceSplitter struct{} + +func (s *serviceSplitter) GetKind() string { + return consulapi.ServiceSplitter +} + +func (s *serviceSplitter) GetDescription() string { + return "The `consul_config_entry_service_splitter` resource configures a [service splitter](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-splitter) that will redirect a percentage of incoming traffic requests for a service to one or more specific service instances." +} + +func (s *serviceSplitter) GetSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "Specifies a name for the configuration entry.", + Required: true, + ForceNew: true, + }, + "partition": { + Type: schema.TypeString, + Description: "Specifies the admin partition to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "namespace": { + Type: schema.TypeString, + Description: "Specifies the namespace to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "meta": { + Type: schema.TypeMap, + Description: "Specifies key-value pairs to add to the KV store.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "splits": { + Type: schema.TypeList, + Description: "Defines how much traffic to send to sets of service instances during a traffic split.", + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "weight": { + Type: schema.TypeFloat, + Description: "Specifies the percentage of traffic sent to the set of service instances specified in the `service` field. Each weight must be a floating integer between `0` and `100`. The smallest representable value is `.01`. The sum of weights across all splits must add up to `100`.", + Required: true, + }, + "service": { + Type: schema.TypeString, + Description: "Specifies the name of the service to resolve.", + Required: true, + }, + "service_subset": { + Type: schema.TypeString, + Description: "Specifies a subset of the service to resolve. A service subset assigns a name to a specific subset of discoverable service instances within a datacenter, such as `version2` or `canary`. All services have an unnamed default subset that returns all healthy instances.", + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Description: "Specifies the namespace to use in the FQDN when resolving the service.", + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Description: "Specifies the admin partition to use in the FQDN when resolving the service.", + Optional: true, + }, + "request_headers": { + Type: schema.TypeList, + MaxItems: 1, + Description: "Specifies a set of HTTP-specific header modification rules applied to requests routed with the service split. You cannot configure request headers if the listener protocol is set to `tcp`.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Description: "Map of one or more key-value pairs. Defines a set of key-value pairs to add to the header. Use header names as the keys. Header names are not case-sensitive. If header values with the same name already exist, the value is appended and Consul applies both headers.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "set": { + Type: schema.TypeMap, + Description: "Map of one or more key-value pairs. Defines a set of key-value pairs to add to the request header or to replace existing header values with. Use header names as the keys. Header names are not case-sensitive. If header values with the same names already exist, Consul replaces the header values.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "remove": { + Type: schema.TypeList, + Description: "Defines an list of headers to remove. Consul removes only headers containing exact matches. Header names are not case-sensitive.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "response_headers": { + Type: schema.TypeList, + MaxItems: 1, + Description: "Specifies a set of HTTP-specific header modification rules applied to responses routed with the service split. You cannot configure request headers if the listener protocol is set to `tcp`.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Description: "Map of one or more key-value pairs. Defines a set of key-value pairs to add to the header. Use header names as the keys. Header names are not case-sensitive. If header values with the same name already exist, the value is appended and Consul applies both headers.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "set": { + Type: schema.TypeMap, + Description: "Map of one or more key-value pairs. Defines a set of key-value pairs to add to the request header or to replace existing header values with. Use header names as the keys. Header names are not case-sensitive. If header values with the same names already exist, Consul replaces the header values.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "remove": { + Type: schema.TypeList, + Description: "Defines an list of headers to remove. Consul removes only headers containing exact matches. Header names are not case-sensitive.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + }, + }, + }, + } +} + +func (s *serviceSplitter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { + configEntry := &consulapi.ServiceSplitterConfigEntry{ + Kind: consulapi.ServiceSplitter, + Name: d.Get("name").(string), + Partition: d.Get("partition").(string), + Namespace: d.Get("namespace").(string), + Meta: map[string]string{}, + } + + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) + } + + for _, raw := range d.Get("splits").([]interface{}) { + s := raw.(map[string]interface{}) + split := consulapi.ServiceSplit{ + Weight: float32(s["weight"].(float64)), + Service: s["service"].(string), + ServiceSubset: s["service_subset"].(string), + Namespace: s["namespace"].(string), + Partition: s["partition"].(string), + RequestHeaders: &consulapi.HTTPHeaderModifiers{ + Add: map[string]string{}, + Set: map[string]string{}, + Remove: []string{}, + }, + ResponseHeaders: &consulapi.HTTPHeaderModifiers{ + Add: map[string]string{}, + Set: map[string]string{}, + Remove: []string{}, + }, + } + + addHeaders := func(modifier *consulapi.HTTPHeaderModifiers, path string) { + elems := s[path].([]interface{}) + if len(elems) == 0 { + return + } + + headers := elems[0].(map[string]interface{}) + for k, v := range headers["add"].(map[string]interface{}) { + modifier.Add[k] = v.(string) + } + for k, v := range headers["set"].(map[string]interface{}) { + modifier.Set[k] = v.(string) + } + for _, v := range headers["remove"].([]interface{}) { + modifier.Remove = append(modifier.Remove, v.(string)) + } + } + addHeaders(split.RequestHeaders, "request_headers") + addHeaders(split.ResponseHeaders, "response_headers") + + configEntry.Splits = append(configEntry.Splits, split) + } + + return configEntry, nil +} + +func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { + sp, ok := ce.(*consulapi.ServiceSplitterConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceSplitter, ce.GetKind()) + } + + sw.set("name", sp.Name) + sw.set("partition", sp.Partition) + sw.set("namespace", sp.Namespace) + + meta := map[string]interface{}{} + for k, v := range sp.Meta { + meta[k] = v + } + sw.set("meta", meta) + + splits := []interface{}{} + for _, s := range sp.Splits { + split := map[string]interface{}{ + "weight": s.Weight, + "service": s.Service, + "service_subset": s.ServiceSubset, + "namespace": s.Namespace, + "partition": s.Partition, + } + addHeaders := func(modifier *consulapi.HTTPHeaderModifiers, path string) { + headers := map[string]interface{}{} + + add := map[string]interface{}{} + for k, v := range modifier.Add { + add[k] = v + } + headers["add"] = add + + set := map[string]interface{}{} + for k, v := range modifier.Set { + set[k] = v + } + headers["set"] = set + + remove := []interface{}{} + for _, v := range modifier.Remove { + remove = append(remove, v) + } + headers["remove"] = remove + + split[path] = []interface{}{headers} + } + addHeaders(s.RequestHeaders, "request_headers") + addHeaders(s.ResponseHeaders, "response_headers") + splits = append(splits, split) + } + sw.set("splits", splits) + + return nil +} diff --git a/consul/resource_consul_config_entry_service_splitter_ce_test.go b/consul/resource_consul_config_entry_service_splitter_ce_test.go new file mode 100644 index 00000000..7f876621 --- /dev/null +++ b/consul/resource_consul_config_entry_service_splitter_ce_test.go @@ -0,0 +1,109 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceSplitterCETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceSplitterCE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), + ), + }, + }, + }) +} + +const testConsulConfigEntryServiceSplitterCE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Protocol = "http" + Expose = {} + MeshGateway = {} + TransparentProxy = {} + }) +} + +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + +resource "consul_config_entry_service_splitter" "foo" { + name = consul_config_entry.service_resolver.name + meta = { + key = "value" + } + splits { + weight = 90 + service_subset = "v1" + service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } + } + splits { + weight = 10 + service = "web" + service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } + } +} +` diff --git a/consul/resource_consul_config_entry_service_splitter_ee_test.go b/consul/resource_consul_config_entry_service_splitter_ee_test.go new file mode 100644 index 00000000..1b18589c --- /dev/null +++ b/consul/resource_consul_config_entry_service_splitter_ee_test.go @@ -0,0 +1,112 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceSplitterEETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceSplitterEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "namespace", "ns"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "partition", "pt"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), + ), + }, + }, + }) +} + +const testConsulConfigEntryServiceSplitterEE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Protocol = "http" + Expose = {} + MeshGateway = {} + TransparentProxy = {} + }) +} + +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + +resource "consul_config_entry_service_splitter" "foo" { + name = consul_config_entry.service_resolver.name + namespace = "ns" + partition = "pt" + meta = { + key = "value" + } + splits { + weight = 90 + service_subset = "v1" + service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } + } + splits { + weight = 10 + service = "web" + service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } + } +} +` diff --git a/consul/resource_consul_service_splitter_config_entry.go b/consul/resource_consul_service_splitter_config_entry.go deleted file mode 100644 index b2200d05..00000000 --- a/consul/resource_consul_service_splitter_config_entry.go +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "fmt" - "strings" - - consulapi "github.com/hashicorp/consul/api" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" -) - -const KindServiceSplitter = "service-splitter" - -var serviceSplitterConfigEntrySchema = map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "kind": { - Type: schema.TypeString, - Required: false, - ForceNew: true, - Computed: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "meta": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "splits": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "weight": { - Type: schema.TypeInt, - Required: true, - }, - "service": { - Type: schema.TypeString, - Required: true, - }, - "service_subset": { - Type: schema.TypeString, - Optional: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - }, - "request_headers": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "add": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "set": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "remove": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "response_headers": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "add": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "set": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "remove": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - }, - }, - }, -} - -func resourceServiceSplitterConfigEntry() *schema.Resource { - - return &schema.Resource{ - Create: resourceConsulServiceSplitterConfigEntryUpdate, - Update: resourceConsulServiceSplitterConfigEntryUpdate, - Read: resourceConsulServiceSplitterConfigEntryRead, - Delete: resourceConsulServiceSplitterConfigEntryDelete, - Importer: &schema.ResourceImporter{ - State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - parts := strings.Split(d.Id(), "/") - var kind, name, partition, namespace string - switch len(parts) { - case 2: - kind = parts[0] - name = parts[1] - case 4: - partition = parts[0] - namespace = parts[1] - kind = parts[2] - name = parts[3] - default: - return nil, fmt.Errorf(`expected path of the form "/" or "///"`) - } - - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - sw := newStateWriter(d) - sw.set("kind", kind) - sw.set("name", name) - sw.set("partition", partition) - sw.set("namespace", namespace) - - err := sw.error() - if err != nil { - return nil, err - } - - return []*schema.ResourceData{d}, nil - }, - }, - Schema: serviceSplitterConfigEntrySchema, - } -} - -func resourceConsulServiceSplitterConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { - client, qOpts, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - - name := d.Get("name").(string) - - configMap := make(map[string]interface{}) - configMap["kind"] = KindServiceSplitter - - configMap["name"] = name - - kind := configMap["kind"].(string) - err := d.Set("kind", kind) - - if err != nil { - return err - } - - var attributes []string - - for key, _ := range serviceSplitterConfigEntrySchema { - attributes = append(attributes, key) - } - - for _, attribute := range attributes { - configMap[attribute] = d.Get(attribute) - } - - formattedMap, err := formatKeys(configMap, formatKey) - if err != nil { - return err - } - - configEntry, err := makeServiceSplitterConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) - if err != nil { - return err - } - - if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { - return fmt.Errorf("failed to set '%s' config entry: %v", name, err) - } - _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) - if err != nil { - if strings.Contains(err.Error(), "Unexpected response code: 404") { - return fmt.Errorf(`failed to read config entry after setting it. -This may happen when some attributes have an unexpected value. -Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html -to see what values are expected`, configEntry.GetKind()) - } - return fmt.Errorf("failed to read config entry: %v", err) - } - - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - return resourceConsulServiceSplitterConfigEntryRead(d, meta) -} - -func resourceConsulServiceSplitterConfigEntryRead(d *schema.ResourceData, meta interface{}) error { - client, qOpts, _ := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) - - fixQOptsForConfigEntry(configName, configKind, qOpts) - - _, _, err := configEntries.Get(configKind, configName, qOpts) - return err -} - -func resourceConsulServiceSplitterConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { - client, _, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) - - if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { - return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) - } - d.SetId("") - return nil -} - -func makeServiceSplitterConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { - configMap["kind"] = KindServiceSplitter - configMap["name"] = name - configMap["Namespace"] = namespace - configMap["Partition"] = partition - - configEntry, err := consulapi.DecodeConfigEntry(configMap) - if err != nil { - return nil, fmt.Errorf("failed to decode config entry: %v", err) - } - - return configEntry, nil -} diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go index c28a450b..5930e557 100644 --- a/consul/resource_consul_service_splitter_config_entry_ce_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ce_test.go @@ -4,8 +4,9 @@ package consul import ( - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" ) func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { @@ -18,19 +19,19 @@ func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { { Config: testConsulServiceSplitterConfigEntryCE, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.#", "2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.request_headers.810692046.set.x-web-version", "from-v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.response_headers.3374032271.set.x-web-version", "to-v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.request_headers.585597472.set.x-web-version", "from-v2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.response_headers.3685616225.set.x-web-version", "to-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), ), }, }, @@ -68,14 +69,14 @@ resource "consul_config_entry" "service_resolver" { }) } -resource "consul_service_splitter_config_entry" "foo" { +resource "consul_config_entry_service_splitter" "foo" { name = consul_config_entry.service_resolver.name meta = { key = "value" } splits { - weight = 90 - service_subset = "v1" + weight = 90 + service_subset = "v1" service = "web" request_headers { set = { diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go index c84300cf..dc69ee79 100644 --- a/consul/resource_consul_service_splitter_config_entry_ee_test.go +++ b/consul/resource_consul_service_splitter_config_entry_ee_test.go @@ -4,8 +4,9 @@ package consul import ( - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" ) func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { @@ -18,21 +19,21 @@ func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { { Config: testConsulServiceSplitterConfigEntryEE, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "name", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "namespace", "ns"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "partition", "pt"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.#", "2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.weight", "90"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.request_headers.810692046.set.x-web-version", "from-v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.0.response_headers.3374032271.set.x-web-version", "to-v1"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.weight", "10"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service_subset", "v2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.service", "web"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.request_headers.585597472.set.x-web-version", "from-v2"), - resource.TestCheckResourceAttr("consul_service_splitter_config_entry.foo", "splits.1.response_headers.3685616225.set.x-web-version", "to-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "namespace", "ns"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "partition", "pt"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), ), }, }, @@ -70,7 +71,7 @@ resource "consul_config_entry" "service_resolver" { }) } -resource "consul_service_splitter_config_entry" "foo" { +resource "consul_config_entry_service_splitter" "foo" { name = consul_config_entry.service_resolver.name namespace = "ns" partition = "pt" @@ -78,8 +79,8 @@ resource "consul_service_splitter_config_entry" "foo" { key = "value" } splits { - weight = 90 - service_subset = "v1" + weight = 90 + service_subset = "v1" service = "web" request_headers { set = { diff --git a/consul/resource_provider.go b/consul/resource_provider.go index d3b982fe..281f3c7b 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -229,30 +229,30 @@ func Provider() terraform.ResourceProvider { "consul_acl_binding_rule": resourceConsulACLBindingRule(), "consul_acl_policy": resourceConsulACLPolicy(), "consul_acl_role": resourceConsulACLRole(), - "consul_acl_token": resourceConsulACLToken(), "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), + "consul_acl_token": resourceConsulACLToken(), "consul_admin_partition": resourceConsulAdminPartition(), "consul_agent_service": resourceConsulAgentService(), + "consul_autopilot_config": resourceConsulAutopilotConfig(), "consul_catalog_entry": resourceConsulCatalogEntry(), "consul_certificate_authority": resourceConsulCertificateAuthority(), + "consul_config_entry_service_splitter": resourceFromConfigEntryImplementation(&serviceSplitter{}), "consul_config_entry": resourceConsulConfigEntry(), - "consul_keys": resourceConsulKeys(), + "consul_intention": resourceConsulIntention(), "consul_key_prefix": resourceConsulKeyPrefix(), + "consul_keys": resourceConsulKeys(), "consul_license": resourceConsulLicense(), - "consul_namespace": resourceConsulNamespace(), "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), - "consul_node": resourceConsulNode(), - "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_autopilot_config": resourceConsulAutopilotConfig(), - "consul_service": resourceConsulService(), - "consul_intention": resourceConsulIntention(), + "consul_namespace": resourceConsulNamespace(), "consul_network_area": resourceConsulNetworkArea(), + "consul_node": resourceConsulNode(), "consul_peering_token": resourceSourceConsulPeeringToken(), "consul_peering": resourceSourceConsulPeering(), + "consul_prepared_query": resourceConsulPreparedQuery(), "consul_service_defaults_config_entry": resourceServiceDefaultsConfigEntry(), - "consul_service_splitter_config_entry": resourceServiceSplitterConfigEntry(), + "consul_service": resourceConsulService(), }, ConfigureFunc: providerConfigure, diff --git a/consul/resource_provider_test.go b/consul/resource_provider_test.go index 9c7743d9..dde1a8b1 100644 --- a/consul/resource_provider_test.go +++ b/consul/resource_provider_test.go @@ -350,10 +350,21 @@ func waitForService(t *testing.T, address string) (terraform.ResourceProvider, * t.Fatalf("failed to instantiate client: %v", err) } + logger := func(format string, args ...any) {} + if os.Getenv("TF_ACC_CONSUL_LOG") != "" { + logger = t.Logf + } + var services []*consulapi.ServiceEntry for i := 0; i < 20; i++ { services, _, err = client.Health().Service("consul", "", true, nil) - if err == nil && len(services) == 1 && len(services[0].Node.Meta) == 1 { + if err != nil { + logger("got error while waiting for server to start: %v", err) + } else if len(services) != 1 { + logger("got wrong number of services: %d", len(services)) + } else if len(services[0].Node.Meta) == 0 { + logger("got empty metadata") + } else { return Provider(), client } diff --git a/docs/resources/config_entry_service_splitter.md b/docs/resources/config_entry_service_splitter.md new file mode 100644 index 00000000..b5a94d19 --- /dev/null +++ b/docs/resources/config_entry_service_splitter.md @@ -0,0 +1,68 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_config_entry_service_splitter Resource - terraform-provider-consul" +subcategory: "" +description: |- + The consul_config_entry_service_splitter resource configures a service splitter https://developer.hashicorp.com/consul/docs/connect/config-entries/service-splitter that will redirect a percentage of incoming traffic requests for a service to one or more specific service instances. +--- + +# consul_config_entry_service_splitter (Resource) + +The `consul_config_entry_service_splitter` resource configures a [service splitter](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-splitter) that will redirect a percentage of incoming traffic requests for a service to one or more specific service instances. + + + + +## Schema + +### Required + +- `name` (String) Specifies a name for the configuration entry. +- `splits` (Block List, Min: 1) Defines how much traffic to send to sets of service instances during a traffic split. (see [below for nested schema](#nestedblock--splits)) + +### Optional + +- `meta` (Map of String) Specifies key-value pairs to add to the KV store. +- `namespace` (String) Specifies the namespace to apply the configuration entry. +- `partition` (String) Specifies the admin partition to apply the configuration entry. + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `splits` + +Required: + +- `service` (String) Specifies the name of the service to resolve. +- `weight` (Number) Specifies the percentage of traffic sent to the set of service instances specified in the `service` field. Each weight must be a floating integer between `0` and `100`. The smallest representable value is `.01`. The sum of weights across all splits must add up to `100`. + +Optional: + +- `namespace` (String) Specifies the namespace to use in the FQDN when resolving the service. +- `partition` (String) Specifies the admin partition to use in the FQDN when resolving the service. +- `request_headers` (Block List, Max: 1) Specifies a set of HTTP-specific header modification rules applied to requests routed with the service split. You cannot configure request headers if the listener protocol is set to `tcp`. (see [below for nested schema](#nestedblock--splits--request_headers)) +- `response_headers` (Block List, Max: 1) Specifies a set of HTTP-specific header modification rules applied to responses routed with the service split. You cannot configure request headers if the listener protocol is set to `tcp`. (see [below for nested schema](#nestedblock--splits--response_headers)) +- `service_subset` (String) Specifies a subset of the service to resolve. A service subset assigns a name to a specific subset of discoverable service instances within a datacenter, such as `version2` or `canary`. All services have an unnamed default subset that returns all healthy instances. + + +### Nested Schema for `splits.request_headers` + +Optional: + +- `add` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the header. Use header names as the keys. Header names are not case-sensitive. If header values with the same name already exist, the value is appended and Consul applies both headers. +- `remove` (List of String) Defines an list of headers to remove. Consul removes only headers containing exact matches. Header names are not case-sensitive. +- `set` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the request header or to replace existing header values with. Use header names as the keys. Header names are not case-sensitive. If header values with the same names already exist, Consul replaces the header values. + + + +### Nested Schema for `splits.response_headers` + +Optional: + +- `add` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the header. Use header names as the keys. Header names are not case-sensitive. If header values with the same name already exist, the value is appended and Consul applies both headers. +- `remove` (List of String) Defines an list of headers to remove. Consul removes only headers containing exact matches. Header names are not case-sensitive. +- `set` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the request header or to replace existing header values with. Use header names as the keys. Header names are not case-sensitive. If header values with the same names already exist, Consul replaces the header values. + + diff --git a/docs/resources/service_defaults_config_entry.md b/docs/resources/service_defaults_config_entry.md new file mode 100644 index 00000000..d3780e6a --- /dev/null +++ b/docs/resources/service_defaults_config_entry.md @@ -0,0 +1,209 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_service_defaults_config_entry Resource - terraform-provider-consul" +subcategory: "" +description: |- + +--- + +# consul_service_defaults_config_entry (Resource) + + + + + + +## Schema + +### Required + +- `expose` (Block Set, Min: 1) (see [below for nested schema](#nestedblock--expose)) +- `name` (String) +- `protocol` (String) + +### Optional + +- `balance_inbound_connections` (String) +- `destination` (Block Set) (see [below for nested schema](#nestedblock--destination)) +- `envoy_extensions` (Block List) (see [below for nested schema](#nestedblock--envoy_extensions)) +- `external_sni` (String) +- `local_connect_timeout_ms` (Number) +- `local_request_timeout_ms` (Number) +- `max_inbound_connections` (Number) +- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--mesh_gateway)) +- `meta` (Map of String) +- `mode` (String) +- `mutual_tls_mode` (String) +- `namespace` (String) +- `partition` (String) The partition the config entry is associated with. +- `transparent_proxy` (Block Set) (see [below for nested schema](#nestedblock--transparent_proxy)) +- `upstream_config` (Block Set) (see [below for nested schema](#nestedblock--upstream_config)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `kind` (String) + + +### 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) (see [below for nested schema](#nestedblock--upstream_config--defaults)) +- `overrides` (Block List) (see [below for nested schema](#nestedblock--upstream_config--overrides)) + + +### Nested Schema for `upstream_config.defaults` + +Optional: + +- `balance_outbound_connections` (String) +- `connect_timeout_ms` (String) +- `envoy_cluster_json` (String) +- `envoy_listener_json` (String) +- `limits` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--limits)) +- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--mesh_gateway)) +- `name` (String) +- `namespace` (String) +- `partition` (String) +- `passive_health_check` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--passive_health_check)) +- `peer` (String) +- `protocol` (String) + + +### Nested Schema for `upstream_config.defaults.limits` + +Optional: + +- `max_concurrent_requests` (Number) +- `max_connections` (Number) +- `max_pending_requests` (Number) + + + +### Nested Schema for `upstream_config.defaults.mesh_gateway` + +Optional: + +- `mode` (String) + + + +### Nested Schema for `upstream_config.defaults.passive_health_check` + +Optional: + +- `base_ejection_time` (Number) +- `enforcing_consecutive_5xx` (Number) +- `interval` (Number) +- `max_ejection_percent` (Number) +- `max_failures` (Number) + + + + +### Nested Schema for `upstream_config.overrides` + +Optional: + +- `balance_outbound_connections` (String) +- `connect_timeout_ms` (String) +- `envoy_cluster_json` (String) +- `envoy_listener_json` (String) +- `limits` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--limits)) +- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--mesh_gateway)) +- `name` (String) +- `namespace` (String) +- `partition` (String) +- `passive_health_check` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--passive_health_check)) +- `peer` (String) +- `protocol` (String) + + +### Nested Schema for `upstream_config.overrides.limits` + +Optional: + +- `max_concurrent_requests` (Number) +- `max_connections` (Number) +- `max_pending_requests` (Number) + + + +### Nested Schema for `upstream_config.overrides.mesh_gateway` + +Optional: + +- `mode` (String) + + + +### Nested Schema for `upstream_config.overrides.passive_health_check` + +Optional: + +- `base_ejection_time` (Number) +- `enforcing_consecutive_5xx` (Number) +- `interval` (Number) +- `max_ejection_percent` (Number) +- `max_failures` (Number) + + From 08d5184fd4d2d51d3459f125da5cda89b3bdfd15 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 13:27:38 +0530 Subject: [PATCH 32/89] code service defaults config entry --- ...ce_consul_config_entry_service_defaults.go | 641 ++++++++++++++++++ ..._config_entry_service_defaults_ce_test.go} | 0 ..._config_entry_service_defaults_ee_test.go} | 0 ...ce_consul_service_defaults_config_entry.go | 490 ------------- ...l_service_splitter_config_entry_ce_test.go | 108 --- ...l_service_splitter_config_entry_ee_test.go | 112 --- consul/resource_provider.go | 1 + 7 files changed, 642 insertions(+), 710 deletions(-) create mode 100644 consul/resource_consul_config_entry_service_defaults.go rename consul/{resource_consul_service_defaults_config_entry_ce_test.go => resource_consul_config_entry_service_defaults_ce_test.go} (100%) rename consul/{resource_consul_service_defaults_config_entry_ee_test.go => resource_consul_config_entry_service_defaults_ee_test.go} (100%) delete mode 100644 consul/resource_consul_service_defaults_config_entry.go delete mode 100644 consul/resource_consul_service_splitter_config_entry_ce_test.go delete mode 100644 consul/resource_consul_service_splitter_config_entry_ee_test.go 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..09d766e9 --- /dev/null +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -0,0 +1,641 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "time" +) + +type serviceDefaults struct{} + +func (s *serviceDefaults) GetKind() string { + return consulapi.ServiceSplitter +} + +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) that contains common configuration settings for service mesh services, such as upstreams and gateways." +} + +func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { + upstreamConfigSchema := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_listener_json": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_cluster_json": { + Type: schema.TypeString, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + }, + "connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + "limits": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + }, + "passive_health_check": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeString, + Optional: true, + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + }, + "base_ejection_time": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "balance_outbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + }, + } + return map[string]*schema.Schema{ + "kind": { + Type: schema.TypeString, + Required: false, + ForceNew: true, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The partition the config entry is associated with.", + }, + + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + }, + + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + }, + + "mode": { + Type: schema.TypeString, + Optional: true, + }, + + "upstream_config": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "overrides": { + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchema, + }, + "defaults": { + Type: schema.TypeSet, + Optional: true, + Elem: upstreamConfigSchema, + }, + }, + }, + }, + + "transparent_proxy": { + Type: schema.TypeSet, + Optional: true, + 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, + }, + + "envoy_extensions": { + Type: schema.TypeList, + Optional: true, + 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, + 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, + }, + + "max_inbound_connections": { + Type: schema.TypeInt, + Optional: true, + }, + + "local_request_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Required: true, + Type: schema.TypeString, + }, + }, + }, + }, + + "external_sni": { + Type: schema.TypeString, + Optional: true, + }, + + "expose": { + Type: schema.TypeSet, + Required: true, + 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), + Namespace: d.Get("namespace").(string), + Meta: map[string]string{}, + } + + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) + } + + configEntry.Protocol = d.Get("protocol").(string) + configEntry.BalanceInboundConnections = d.Get("balance_inbound_connections").(string) + + proxyMode := consulapi.ProxyMode(d.Get("mode").(string)) + configEntry.Mode = proxyMode + + getLimits := func(limitsMap map[string]interface{}) *consulapi.UpstreamLimits { + upstreamLimit := &consulapi.UpstreamLimits{} + upstreamLimit.MaxPendingRequests = limitsMap["max_pending_requests"].(*int) + upstreamLimit.MaxConnections = limitsMap["max_connections"].(*int) + upstreamLimit.MaxConcurrentRequests = limitsMap["max_concurrent_requests"].(*int) + return upstreamLimit + } + + getPassiveHealthCheck := func(passiveHealthCheckSet interface{}) (*consulapi.PassiveHealthCheck, error) { + passiveHealthCheck := passiveHealthCheckSet.(*schema.Set).List() + if len(passiveHealthCheck) > 0 { + passiveHealthCheckMap := passiveHealthCheck[0].(map[string]interface{}) + passiveHealthCheck := &consulapi.PassiveHealthCheck{} + duration, err := time.ParseDuration(passiveHealthCheckMap["interval"].(string)) + if err != nil { + return nil, err + } + passiveHealthCheck.Interval = duration + passiveHealthCheck.MaxFailures = passiveHealthCheckMap["max_failures"].(uint32) + passiveHealthCheck.EnforcingConsecutive5xx = passiveHealthCheckMap["enforcing_consecutive_5xx"].(*uint32) + passiveHealthCheck.MaxEjectionPercent = passiveHealthCheckMap["max_ejection_percent"].(*uint32) + baseEjectionTime, err := time.ParseDuration(passiveHealthCheckMap["base_ejection_time"].(string)) + if err != nil { + return nil, 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{}) + meshGatewayMode := consulapi.MeshGatewayMode(meshGatewayData["mode"].(string)) + meshGateway := &consulapi.MeshGatewayConfig{} + meshGateway.Mode = meshGatewayMode + return meshGateway + } + return nil + } + + getUpstreamConfig := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { + upstreamConfig := &consulapi.UpstreamConfig{} + upstreamConfig.Name = upstreamConfigMap["name"].(string) + upstreamConfig.Partition = upstreamConfigMap["partition"].(string) + upstreamConfig.Namespace = upstreamConfigMap["namespace"].(string) + upstreamConfig.Peer = upstreamConfigMap["peer"].(string) + upstreamConfig.EnvoyListenerJSON = upstreamConfigMap["envoy_listener_json"].(string) + upstreamConfig.EnvoyClusterJSON = upstreamConfigMap["envoy_cluster_json"].(string) + upstreamConfig.Protocol = upstreamConfigMap["protocol"].(string) + upstreamConfig.ConnectTimeoutMs = upstreamConfigMap["connect_timeout_ms"].(int) + upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(map[string]interface{})) + passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) + if err != nil { + return nil, err + } + upstreamConfig.PassiveHealthCheck = passiveHealthCheck + upstreamConfig.MeshGateway = *getMeshGateway(upstreamConfigMap["mesh_gateway"]) + upstreamConfig.BalanceOutboundConnections = upstreamConfigMap["balance_outbound_connections"].(string) + return upstreamConfig, nil + } + + getTransparentProxy := func(transparentProxy map[string]interface{}) *consulapi.TransparentProxyConfig { + tProxy := &consulapi.TransparentProxyConfig{} + tProxy.OutboundListenerPort = transparentProxy["outbound_listener_port"].(int) + tProxy.DialedDirectly = transparentProxy["dialed_directly"].(bool) + return tProxy + } + + getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) *consulapi.EnvoyExtension { + envoyExtension := &consulapi.EnvoyExtension{} + envoyExtension.Name = envoyExtensionMap["name"].(string) + envoyExtension.Required = envoyExtensionMap["required"].(bool) + envoyExtension.Arguments = envoyExtensionMap["arguments"].(map[string]interface{}) + envoyExtension.ConsulVersion = envoyExtensionMap["consul_version"].(string) + envoyExtension.EnvoyVersion = envoyExtensionMap["envoy_version"].(string) + return envoyExtension + } + + getDestination := func(destinationMap map[string]interface{}) *consulapi.DestinationConfig { + var destination consulapi.DestinationConfig + destination.Port = destinationMap["port"].(int) + destination.Addresses = destinationMap["addresses"].([]string) + return &destination + } + + getExposePath := func(exposePathMap map[string]interface{}) *consulapi.ExposePath { + exposePath := &consulapi.ExposePath{} + exposePath.Path = exposePathMap["path"].(string) + exposePath.LocalPathPort = exposePathMap["local_path_port"].(int) + exposePath.ListenerPort = exposePathMap["listener_port"].(int) + exposePath.Protocol = exposePathMap["protocol"].(string) + return exposePath + } + + getExpose := func(exposeMap map[string]interface{}) consulapi.ExposeConfig { + var exposeConfig consulapi.ExposeConfig + exposeConfig.Checks = exposeMap["checks"].(bool) + var paths []consulapi.ExposePath + for _, elem := range exposeMap["paths"].([]interface{}) { + paths = append(paths, *getExposePath(elem.(map[string]interface{}))) + } + exposeConfig.Paths = paths + return exposeConfig + } + + upstreamConfigMap := d.Get("upstream_config").(map[string]interface{}) + defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() + if len(defaultsUpstreamConfigMapList) > 0 { + defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) + if err != nil { + return nil, err + } + configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig + } + + overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) + var overrideUpstreamConfig []*consulapi.UpstreamConfig + for _, elem := range overrideUpstreamConfigList { + overrideUpstreamConfigList := elem.(*schema.Set).List() + if len(overrideUpstreamConfigList) > 0 { + overrideUpstreamConfigElem, err := getUpstreamConfig(overrideUpstreamConfigList[0].(map[string]interface{})) + if err != nil { + return nil, err + } + overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) + } + } + configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig + + transparentProxyList := d.Get("transparent_proxy").(*schema.Set).List() + if len(transparentProxyList) > 0 { + transparentProxy := transparentProxyList[0].(map[string]interface{}) + configEntry.TransparentProxy = getTransparentProxy(transparentProxy) + } + + mutualTLSmode := consulapi.MutualTLSMode(d.Get("mutual_tls_mode").(string)) + configEntry.MutualTLSMode = mutualTLSmode + + var envoyExtensions []consulapi.EnvoyExtension + + for _, elem := range d.Get("envoy_extensions").([]interface{}) { + envoyExtensionMap := elem.(map[string]interface{}) + envoyExtensions = append(envoyExtensions, *getEnvoyExtension(envoyExtensionMap)) + } + configEntry.EnvoyExtensions = envoyExtensions + + destinationList := d.Get("destination").(*schema.Set).List() + if len(destinationList) > 0 { + configEntry.Destination = getDestination(destinationList[0].(map[string]interface{})) + } + + configEntry.LocalConnectTimeoutMs = d.Get("local_connect_timeout_ms").(int) + configEntry.MaxInboundConnections = d.Get("max_inbound_connections").(int) + configEntry.LocalRequestTimeoutMs = d.Get("local_request_timeout_ms").(int) + + configEntry.MeshGateway = *getMeshGateway(d.Get("mesh_gateway")) + configEntry.ExternalSNI = d.Get("external_sni").(string) + + 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, sw *stateWriter) error { + sp, ok := ce.(*consulapi.ServiceConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceDefaults, ce.GetKind()) + } + + sw.set("name", sp.Name) + sw.set("partition", sp.Partition) + sw.set("namespace", sp.Partition) + + var meta map[string]interface{} + for k, v := range sp.Meta { + meta[k] = v + } + sw.set("meta", meta) + + sw.set("protocol", sp.Protocol) + sw.set("balance_inbound_connections", sp.BalanceInboundConnections) + sw.set("mode", sp.Mode) + + getUpstreamConfig := func(elem *consulapi.UpstreamConfig) map[string]interface{} { + var upstreamConfig map[string]interface{} + upstreamConfig["name"] = elem.Name + upstreamConfig["partition"] = elem.Partition + upstreamConfig["namespace"] = elem.Namespace + upstreamConfig["peer"] = elem.Peer + upstreamConfig["envoy_listener_json"] = elem.EnvoyListenerJSON + upstreamConfig["envoy_cluster_json"] = elem.EnvoyClusterJSON + upstreamConfig["protocol"] = elem.Protocol + upstreamConfig["connect_timeout_ms"] = elem.ConnectTimeoutMs + var limits map[string]interface{} + limits["max_connections"] = elem.Limits.MaxConnections + limits["max_pending_requests"] = elem.Limits.MaxPendingRequests + limits["max_concurrent_requests"] = elem.Limits.MaxConcurrentRequests + upstreamConfig["limits"] = limits + var passiveHealthCheck map[string]interface{} + passiveHealthCheck["interval"] = elem.PassiveHealthCheck.Interval + passiveHealthCheck["max_failures"] = elem.PassiveHealthCheck.MaxFailures + passiveHealthCheck["enforcing_consecutive_5xx"] = elem.PassiveHealthCheck.EnforcingConsecutive5xx + passiveHealthCheck["max_ejection_percent"] = elem.PassiveHealthCheck.MaxEjectionPercent + passiveHealthCheck["base_ejection_time"] = elem.PassiveHealthCheck.BaseEjectionTime + upstreamConfig["passive_health_check"] = passiveHealthCheck + + var meshGateway map[string]interface{} + meshGateway["mode"] = elem.MeshGateway.Mode + upstreamConfig["mesh_gateway"] = meshGateway + + upstreamConfig["balance_outbound_connections"] = elem.BalanceOutboundConnections + return upstreamConfig + } + + var overrides []interface{} + for _, elem := range sp.UpstreamConfig.Overrides { + overrides = append(overrides, getUpstreamConfig(elem)) + } + + var upstreamConfig map[string]interface{} + upstreamConfig["overrides"] = overrides + upstreamConfig["defaults"] = getUpstreamConfig(sp.UpstreamConfig.Defaults) + sw.set("upstream_config", upstreamConfig) + + var transparentProxy map[string]interface{} + transparentProxy["outbound_listener_port"] = sp.TransparentProxy.OutboundListenerPort + transparentProxy["dialed_directly"] = sp.TransparentProxy.DialedDirectly + sw.set("transparent_proxy", transparentProxy) + + sw.set("mutual_tls_mode", sp.MutualTLSMode) + + getEnvoyExtension := func(elem consulapi.EnvoyExtension) map[string]interface{} { + var envoyExtension map[string]interface{} + envoyExtension["name"] = elem.Name + envoyExtension["required"] = elem.Required + var arguments 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 sp.EnvoyExtensions { + envoyExtensions = append(envoyExtensions, getEnvoyExtension(elem)) + } + sw.set("envoy_extensions", envoyExtensions) + + destination := make(map[string]interface{}) + destination["port"] = sp.Destination.Port + destination["addresses"] = sp.Destination.Addresses + sw.set("destination", destination) + + sw.set("local_connect_timeout_ms", sp.LocalConnectTimeoutMs) + sw.set("max_inbound_connections", sp.MaxInboundConnections) + sw.set("local_request_timeout_ms", sp.LocalRequestTimeoutMs) + + meshGateway := make(map[string]interface{}) + meshGateway["mode"] = sp.MeshGateway.Mode + sw.set("mesh_gateway", meshGateway) + + sw.set("external_sni", sp.ExternalSNI) + + expose := make(map[string]interface{}) + expose["checks"] = sp.Expose.Checks + var paths []map[string]interface{} + for _, elem := range sp.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["paths"] = paths + sw.set("expose", expose) + + return nil +} diff --git a/consul/resource_consul_service_defaults_config_entry_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go similarity index 100% rename from consul/resource_consul_service_defaults_config_entry_ce_test.go rename to consul/resource_consul_config_entry_service_defaults_ce_test.go diff --git a/consul/resource_consul_service_defaults_config_entry_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go similarity index 100% rename from consul/resource_consul_service_defaults_config_entry_ee_test.go rename to consul/resource_consul_config_entry_service_defaults_ee_test.go diff --git a/consul/resource_consul_service_defaults_config_entry.go b/consul/resource_consul_service_defaults_config_entry.go deleted file mode 100644 index c47e260d..00000000 --- a/consul/resource_consul_service_defaults_config_entry.go +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "encoding/json" - "fmt" - "strings" - - consulapi "github.com/hashicorp/consul/api" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" -) - -const KindServiceDefaults = "service-defaults" - -var upstreamConfigSchema = &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - "peer": { - Type: schema.TypeString, - Optional: true, - }, - "envoy_listener_json": { - Type: schema.TypeString, - Optional: true, - }, - "envoy_cluster_json": { - Type: schema.TypeString, - Optional: true, - }, - "protocol": { - Type: schema.TypeString, - Optional: true, - }, - "connect_timeout_ms": { - Type: schema.TypeString, - Optional: true, - }, - "limits": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "max_connections": { - Type: schema.TypeInt, - Optional: true, - }, - "max_pending_requests": { - Type: schema.TypeInt, - Optional: true, - }, - "max_concurrent_requests": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - }, - "passive_health_check": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "interval": { - Type: schema.TypeInt, - Optional: true, - }, - "max_failures": { - Type: schema.TypeInt, - Optional: true, - }, - "enforcing_consecutive_5xx": { - Type: schema.TypeInt, - Optional: true, - }, - "max_ejection_percent": { - Type: schema.TypeInt, - Optional: true, - }, - "base_ejection_time": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - }, - "mesh_gateway": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Type: schema.TypeString, - Optional: true, - }, - }, - }, - }, - "balance_outbound_connections": { - Type: schema.TypeString, - Optional: true, - }, - }, -} - -var serviceDefaultsConfigEntrySchema = map[string]*schema.Schema{ - "kind": { - Type: schema.TypeString, - Required: false, - ForceNew: true, - Computed: true, - }, - - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "namespace": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - - "partition": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "The partition the config entry is associated with.", - }, - - "meta": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - - "protocol": { - Type: schema.TypeString, - Required: true, - }, - - "balance_inbound_connections": { - Type: schema.TypeString, - Optional: true, - }, - - "mode": { - Type: schema.TypeString, - Optional: true, - }, - - "upstream_config": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "overrides": { - Type: schema.TypeList, - Optional: true, - Elem: upstreamConfigSchema, - }, - "defaults": { - Type: schema.TypeSet, - Optional: true, - Elem: upstreamConfigSchema, - }, - }, - }, - }, - - "transparent_proxy": { - Type: schema.TypeSet, - Optional: true, - 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, - }, - - "envoy_extensions": { - Type: schema.TypeList, - Optional: true, - 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, - 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, - }, - - "max_inbound_connections": { - Type: schema.TypeInt, - Optional: true, - }, - - "local_request_timeout_ms": { - Type: schema.TypeInt, - Optional: true, - }, - - "mesh_gateway": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Required: true, - Type: schema.TypeString, - }, - }, - }, - }, - - "external_sni": { - Type: schema.TypeString, - Optional: true, - }, - - "expose": { - Type: schema.TypeSet, - Required: true, - 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 resourceServiceDefaultsConfigEntry() *schema.Resource { - - return &schema.Resource{ - Create: resourceConsulServiceDefaultsConfigEntryUpdate, - Update: resourceConsulServiceDefaultsConfigEntryUpdate, - Read: resourceConsulServiceDefaultsConfigEntryRead, - Delete: resourceConsulServiceDefaultsConfigEntryDelete, - Importer: &schema.ResourceImporter{ - State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - parts := strings.Split(d.Id(), "/") - var kind, name, partition, namespace string - switch len(parts) { - case 2: - kind = parts[0] - name = parts[1] - case 4: - partition = parts[0] - namespace = parts[1] - kind = parts[2] - name = parts[3] - default: - return nil, fmt.Errorf(`expected path of the form "/" or "///"`) - } - - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - sw := newStateWriter(d) - sw.set("kind", kind) - sw.set("name", name) - sw.set("partition", partition) - sw.set("namespace", namespace) - - err := sw.error() - if err != nil { - return nil, err - } - - return []*schema.ResourceData{d}, nil - }, - }, - Schema: serviceDefaultsConfigEntrySchema, - } -} - -func resourceConsulServiceDefaultsConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { - client, qOpts, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - - name := d.Get("name").(string) - - configMap := make(map[string]interface{}) - - configMap["kind"] = KindServiceDefaults - - configMap["name"] = name - - kind := configMap["kind"].(string) - err := d.Set("kind", kind) - - if err != nil { - return err - } - - var attributes []string - - for key, _ := range serviceDefaultsConfigEntrySchema { - attributes = append(attributes, key) - } - - for _, attribute := range attributes { - configMap[attribute] = d.Get(attribute) - } - - formattedMap, err := formatKeys(configMap, formatKey) - - if err != nil { - return err - } - - configEntry, err := makeServiceDefaultsConfigEntry(name, formattedMap.(map[string]interface{}), wOpts.Namespace, wOpts.Partition) - if err != nil { - return err - } - - if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { - return fmt.Errorf("failed to set '%s' config entry: %v", name, err) - } - _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) - if err != nil { - if strings.Contains(err.Error(), "Unexpected response code: 404") { - return fmt.Errorf(`failed to read config entry after setting it. -This may happen when some attributes have an unexpected value. -Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html -to see what values are expected`, configEntry.GetKind()) - } - return fmt.Errorf("failed to read config entry: %v", err) - } - - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - return resourceConsulServiceDefaultsConfigEntryRead(d, meta) -} - -func resourceConsulServiceDefaultsConfigEntryRead(d *schema.ResourceData, meta interface{}) error { - var attributes []string - - for key, _ := range serviceDefaultsConfigEntrySchema { - attributes = append(attributes, key) - } - - client, qOpts, _ := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) - - configEntry, _, err := configEntries.Get(configKind, configName, qOpts) - - _, _, configJSON, err := parseConfigEntry(configEntry) - if err != nil { - return fmt.Errorf("failed to parse ConfigEntry: %v", err) - } - - configJsonMap := make(map[string]interface{}) - - err = json.Unmarshal([]byte(configJSON), &configJsonMap) - if err != nil { - return err - } - - for _, attribute := range attributes { - value := configJsonMap[formatKey(attribute)] - if err = d.Set(attribute, value); err != nil { - return fmt.Errorf("failed to set attribute': %v with value %v", attribute, configJsonMap[formatKey(attribute)]) - } - } - - return err -} - -func resourceConsulServiceDefaultsConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { - client, _, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) - - if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { - return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) - } - d.SetId("") - return nil -} - -func makeServiceDefaultsConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { - configMap["kind"] = KindServiceDefaults - configMap["name"] = name - configMap["Namespace"] = namespace - configMap["Partition"] = partition - - configEntry, err := consulapi.DecodeConfigEntry(configMap) - if err != nil { - return nil, fmt.Errorf("failed to decode config entry: %v", err) - } - - return configEntry, nil -} diff --git a/consul/resource_consul_service_splitter_config_entry_ce_test.go b/consul/resource_consul_service_splitter_config_entry_ce_test.go deleted file mode 100644 index 5930e557..00000000 --- a/consul/resource_consul_service_splitter_config_entry_ce_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" -) - -func TestAccConsulServiceSplitterConfigCEEntryTest(t *testing.T) { - providers, _ := startTestServer(t) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, - Providers: providers, - Steps: []resource.TestStep{ - { - Config: testConsulServiceSplitterConfigEntryCE, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), - ), - }, - }, - }) -} - -const testConsulServiceSplitterConfigEntryCE = ` -resource "consul_config_entry" "web" { - name = "web" - kind = "service-defaults" - - config_json = jsonencode({ - Protocol = "http" - Expose = {} - MeshGateway = {} - TransparentProxy = {} - }) -} - -resource "consul_config_entry" "service_resolver" { - kind = "service-resolver" - name = consul_config_entry.web.name - - config_json = jsonencode({ - DefaultSubset = "v1" - - Subsets = { - "v1" = { - Filter = "Service.Meta.version == v1" - } - "v2" = { - Filter = "Service.Meta.version == v2" - } - } - }) -} - -resource "consul_config_entry_service_splitter" "foo" { - name = consul_config_entry.service_resolver.name - meta = { - key = "value" - } - splits { - weight = 90 - service_subset = "v1" - service = "web" - request_headers { - set = { - "x-web-version": "from-v1" - } - } - response_headers { - set = { - "x-web-version": "to-v1" - } - } - } - splits { - weight = 10 - service = "web" - service_subset = "v2" - request_headers { - set = { - "x-web-version": "from-v2" - } - } - response_headers { - set = { - "x-web-version": "to-v2" - } - } - } -} -` diff --git a/consul/resource_consul_service_splitter_config_entry_ee_test.go b/consul/resource_consul_service_splitter_config_entry_ee_test.go deleted file mode 100644 index dc69ee79..00000000 --- a/consul/resource_consul_service_splitter_config_entry_ee_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" -) - -func TestAccConsulServiceSplitterConfigEEEntryTest(t *testing.T) { - providers, _ := startTestServer(t) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, - Providers: providers, - Steps: []resource.TestStep{ - { - Config: testConsulServiceSplitterConfigEntryEE, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "namespace", "ns"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "partition", "pt"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), - ), - }, - }, - }) -} - -const testConsulServiceSplitterConfigEntryEE = ` -resource "consul_config_entry" "web" { - name = "web" - kind = "service-defaults" - - config_json = jsonencode({ - Protocol = "http" - Expose = {} - MeshGateway = {} - TransparentProxy = {} - }) -} - -resource "consul_config_entry" "service_resolver" { - kind = "service-resolver" - name = consul_config_entry.web.name - - config_json = jsonencode({ - DefaultSubset = "v1" - - Subsets = { - "v1" = { - Filter = "Service.Meta.version == v1" - } - "v2" = { - Filter = "Service.Meta.version == v2" - } - } - }) -} - -resource "consul_config_entry_service_splitter" "foo" { - name = consul_config_entry.service_resolver.name - namespace = "ns" - partition = "pt" - meta = { - key = "value" - } - splits { - weight = 90 - service_subset = "v1" - service = "web" - request_headers { - set = { - "x-web-version": "from-v1" - } - } - response_headers { - set = { - "x-web-version": "to-v1" - } - } - } - splits { - weight = 10 - service = "web" - service_subset = "v2" - request_headers { - set = { - "x-web-version": "from-v2" - } - } - response_headers { - set = { - "x-web-version": "to-v2" - } - } - } -} -` diff --git a/consul/resource_provider.go b/consul/resource_provider.go index 281f3c7b..e9e8bc23 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -238,6 +238,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(), From d82a7d279c0979bee1a278d3d4484f41f61a11e7 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 13:41:05 +0530 Subject: [PATCH 33/89] fix resource provider --- consul/resource_provider.go | 1 - 1 file changed, 1 deletion(-) diff --git a/consul/resource_provider.go b/consul/resource_provider.go index e9e8bc23..c32e164b 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -252,7 +252,6 @@ func Provider() terraform.ResourceProvider { "consul_peering_token": resourceSourceConsulPeeringToken(), "consul_peering": resourceSourceConsulPeering(), "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_service_defaults_config_entry": resourceServiceDefaultsConfigEntry(), "consul_service": resourceConsulService(), }, From d6ec4fb862600491f003e816cd659a5b88c64d18 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 15:18:34 +0530 Subject: [PATCH 34/89] fixes during testing --- ...ce_consul_config_entry_service_defaults.go | 124 +++++++++++------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 09d766e9..95402b13 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -13,7 +13,7 @@ import ( type serviceDefaults struct{} func (s *serviceDefaults) GetKind() string { - return consulapi.ServiceSplitter + return consulapi.ServiceDefaults } func (s *serviceDefaults) GetDescription() string { @@ -353,9 +353,18 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, getLimits := func(limitsMap map[string]interface{}) *consulapi.UpstreamLimits { upstreamLimit := &consulapi.UpstreamLimits{} - upstreamLimit.MaxPendingRequests = limitsMap["max_pending_requests"].(*int) - upstreamLimit.MaxConnections = limitsMap["max_connections"].(*int) - upstreamLimit.MaxConcurrentRequests = limitsMap["max_concurrent_requests"].(*int) + var maxPendingRequests *int + maxPendingRequests = new(int) + *maxPendingRequests = limitsMap["max_pending_requests"].(int) + upstreamLimit.MaxPendingRequests = maxPendingRequests + var maxConnections *int + maxConnections = new(int) + *maxConnections = limitsMap["max_connections"].(int) + upstreamLimit.MaxConnections = maxConnections + var maxConcurrentRequests *int + maxConcurrentRequests = new(int) + *maxConcurrentRequests = limitsMap["max_concurrent_requests"].(int) + upstreamLimit.MaxConcurrentRequests = maxConcurrentRequests return upstreamLimit } @@ -369,9 +378,16 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return nil, err } passiveHealthCheck.Interval = duration - passiveHealthCheck.MaxFailures = passiveHealthCheckMap["max_failures"].(uint32) - passiveHealthCheck.EnforcingConsecutive5xx = passiveHealthCheckMap["enforcing_consecutive_5xx"].(*uint32) - passiveHealthCheck.MaxEjectionPercent = passiveHealthCheckMap["max_ejection_percent"].(*uint32) + passiveHealthCheck.MaxFailures = uint32(passiveHealthCheckMap["max_failures"].(int)) + var enforcingConsecutive5xx *uint32 + enforcingConsecutive5xx = new(uint32) + *enforcingConsecutive5xx = uint32(passiveHealthCheckMap["enforcing_consecutive_5xx"].(int)) + passiveHealthCheck.EnforcingConsecutive5xx = enforcingConsecutive5xx + var maxEjectionPercentage *uint32 + maxEjectionPercentage = new(uint32) + *maxEjectionPercentage = uint32(passiveHealthCheckMap["max_ejection_percent"].(int)) + passiveHealthCheck.EnforcingConsecutive5xx = enforcingConsecutive5xx + passiveHealthCheck.MaxEjectionPercent = maxEjectionPercentage baseEjectionTime, err := time.ParseDuration(passiveHealthCheckMap["base_ejection_time"].(string)) if err != nil { return nil, err @@ -404,7 +420,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, upstreamConfig.EnvoyClusterJSON = upstreamConfigMap["envoy_cluster_json"].(string) upstreamConfig.Protocol = upstreamConfigMap["protocol"].(string) upstreamConfig.ConnectTimeoutMs = upstreamConfigMap["connect_timeout_ms"].(int) - upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(map[string]interface{})) + upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})) passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) if err != nil { return nil, err @@ -459,7 +475,9 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return exposeConfig } - upstreamConfigMap := d.Get("upstream_config").(map[string]interface{}) + configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} + + upstreamConfigMap := d.Get("upstream_config").(*schema.Set).List()[0].(map[string]interface{}) defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() if len(defaultsUpstreamConfigMapList) > 0 { defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) @@ -472,14 +490,11 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) var overrideUpstreamConfig []*consulapi.UpstreamConfig for _, elem := range overrideUpstreamConfigList { - overrideUpstreamConfigList := elem.(*schema.Set).List() - if len(overrideUpstreamConfigList) > 0 { - overrideUpstreamConfigElem, err := getUpstreamConfig(overrideUpstreamConfigList[0].(map[string]interface{})) - if err != nil { - return nil, err - } - overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) + overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) + if err != nil { + return nil, err } + overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) } configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig @@ -530,7 +545,7 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error sw.set("partition", sp.Partition) sw.set("namespace", sp.Partition) - var meta map[string]interface{} + meta := make(map[string]interface{}) for k, v := range sp.Meta { meta[k] = v } @@ -541,7 +556,7 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error sw.set("mode", sp.Mode) getUpstreamConfig := func(elem *consulapi.UpstreamConfig) map[string]interface{} { - var upstreamConfig map[string]interface{} + upstreamConfig := make(map[string]interface{}) upstreamConfig["name"] = elem.Name upstreamConfig["partition"] = elem.Partition upstreamConfig["namespace"] = elem.Namespace @@ -550,21 +565,24 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error upstreamConfig["envoy_cluster_json"] = elem.EnvoyClusterJSON upstreamConfig["protocol"] = elem.Protocol upstreamConfig["connect_timeout_ms"] = elem.ConnectTimeoutMs - var limits map[string]interface{} - limits["max_connections"] = elem.Limits.MaxConnections - limits["max_pending_requests"] = elem.Limits.MaxPendingRequests - limits["max_concurrent_requests"] = elem.Limits.MaxConcurrentRequests + 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 - var passiveHealthCheck map[string]interface{} - passiveHealthCheck["interval"] = elem.PassiveHealthCheck.Interval - passiveHealthCheck["max_failures"] = elem.PassiveHealthCheck.MaxFailures - passiveHealthCheck["enforcing_consecutive_5xx"] = elem.PassiveHealthCheck.EnforcingConsecutive5xx - passiveHealthCheck["max_ejection_percent"] = elem.PassiveHealthCheck.MaxEjectionPercent - passiveHealthCheck["base_ejection_time"] = elem.PassiveHealthCheck.BaseEjectionTime + 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 - var meshGateway map[string]interface{} - meshGateway["mode"] = elem.MeshGateway.Mode + 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 @@ -576,23 +594,28 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error overrides = append(overrides, getUpstreamConfig(elem)) } - var upstreamConfig map[string]interface{} + upstreamConfig := make(map[string]interface{}) upstreamConfig["overrides"] = overrides - upstreamConfig["defaults"] = getUpstreamConfig(sp.UpstreamConfig.Defaults) - sw.set("upstream_config", upstreamConfig) - - var transparentProxy map[string]interface{} - transparentProxy["outbound_listener_port"] = sp.TransparentProxy.OutboundListenerPort - transparentProxy["dialed_directly"] = sp.TransparentProxy.DialedDirectly + defaultsSlice := make([]map[string]interface{}, 1) + defaultsSlice[0] = getUpstreamConfig(sp.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"] = sp.TransparentProxy.OutboundListenerPort + transparentProxy[0]["dialed_directly"] = sp.TransparentProxy.DialedDirectly sw.set("transparent_proxy", transparentProxy) sw.set("mutual_tls_mode", sp.MutualTLSMode) getEnvoyExtension := func(elem consulapi.EnvoyExtension) map[string]interface{} { - var envoyExtension map[string]interface{} + envoyExtension := make(map[string]interface{}) envoyExtension["name"] = elem.Name envoyExtension["required"] = elem.Required - var arguments map[string]interface{} + arguments := make(map[string]interface{}) for k, v := range elem.Arguments { arguments[k] = v } @@ -608,23 +631,28 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } sw.set("envoy_extensions", envoyExtensions) - destination := make(map[string]interface{}) - destination["port"] = sp.Destination.Port - destination["addresses"] = sp.Destination.Addresses - sw.set("destination", destination) + destination := make([]map[string]interface{}, 1) + if sp.Destination != nil { + destination[0] = make(map[string]interface{}) + destination[0]["port"] = sp.Destination.Port + destination[0]["addresses"] = sp.Destination.Addresses + sw.set("destination", destination) + } sw.set("local_connect_timeout_ms", sp.LocalConnectTimeoutMs) sw.set("max_inbound_connections", sp.MaxInboundConnections) sw.set("local_request_timeout_ms", sp.LocalRequestTimeoutMs) - meshGateway := make(map[string]interface{}) - meshGateway["mode"] = sp.MeshGateway.Mode + meshGateway := make([]map[string]interface{}, 1) + meshGateway[0] = make(map[string]interface{}) + meshGateway[0]["mode"] = sp.MeshGateway.Mode sw.set("mesh_gateway", meshGateway) sw.set("external_sni", sp.ExternalSNI) - expose := make(map[string]interface{}) - expose["checks"] = sp.Expose.Checks + expose := make([]map[string]interface{}, 1) + expose[0] = make(map[string]interface{}) + expose[0]["checks"] = sp.Expose.Checks var paths []map[string]interface{} for _, elem := range sp.Expose.Paths { path := make(map[string]interface{}) @@ -634,7 +662,7 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error path["protocol"] = elem.Protocol paths = append(paths, path) } - expose["paths"] = paths + expose[0]["paths"] = paths sw.set("expose", expose) return nil From e663022b28cf14764ed8bc2065541db3522f67c8 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 15:35:32 +0530 Subject: [PATCH 35/89] fix resource name in testS --- ...l_config_entry_service_defaults_ce_test.go | 224 ++++++++--------- ...l_config_entry_service_defaults_ee_test.go | 232 +++++++++--------- 2 files changed, 228 insertions(+), 228 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go index ccde80cc..09f2e7eb 100644 --- a/consul/resource_consul_config_entry_service_defaults_ce_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -18,121 +18,121 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { { Config: testConsulServiceDefaultsConfigEntryWithDestination, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "kind", "service-defaults"), + 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_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "kind", "service-defaults"), + 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.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + 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"), ), }, }, @@ -141,7 +141,7 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { // Destination and Upstream Config are exclusive. const testConsulServiceDefaultsConfigEntryWithDestination = ` -resource "consul_service_defaults_config_entry" "foo" { +resource "consul_config_entry_service_defaults" "foo" { name = "service-defaults-test-1" meta = { key = "value" @@ -197,7 +197,7 @@ resource "consul_service_defaults_config_entry" "foo" { ` const testConsulServiceDefaultsConfigEntryWithUpstreamConfig = ` -resource "consul_service_defaults_config_entry" "bar" { +resource "consul_config_entry_service_defaults" "bar" { name = "service-defaults-test-2" meta = { key = "value" diff --git a/consul/resource_consul_config_entry_service_defaults_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go index 1b27dfe1..385b4da9 100644 --- a/consul/resource_consul_config_entry_service_defaults_ee_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ee_test.go @@ -18,125 +18,125 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { { Config: testConsulServiceDefaultsConfigEntryWithDestinationEE, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "name", "service-defaults-test-1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "kind", "service-defaults"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "balance_inbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mode", "test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "transparent_proxy.3186228498.dialed_directly", "true"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mutual_tls_mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.required", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.consul_version", "1.16"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "envoy_extensions.0.envoy_version", "1.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.0", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.addresses.1", "10.0.0.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "destination.2840622507.port", "1000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "max_inbound_connections", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "local_request_timeout_ms", "15"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "mesh_gateway.2285830552.mode", "mode"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "external_sni", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.checks", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.listener_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.local_path_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.path", "/local/dir"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.0.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.listener_port", "20"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.local_path_port", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.path", "/test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "expose.539725082.paths.1.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "kind", "service-defaults"), + 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_service_defaults_config_entry.bar", "name", "service-defaults-test-2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "kind", "service-defaults"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "namespace", "namespace2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.foo", "partition", "partition2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "balance_inbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mode", "test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "transparent_proxy.3186228498.dialed_directly", "true"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mutual_tls_mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.required", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.consul_version", "1.16"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "envoy_extensions.0.envoy_version", "1.2"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "max_inbound_connections", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "local_request_timeout_ms", "15"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "mesh_gateway.3963046091.mode", "strict"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "external_sni", "10.0.0.1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.#", "1"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.checks", "false"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.listener_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.local_path_port", "0"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.path", "/local/dir"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.0.protocol", "http"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.listener_port", "20"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.local_path_port", "10"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.path", "/test"), - resource.TestCheckResourceAttr("consul_service_defaults_config_entry.bar", "expose.539725082.paths.1.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "kind", "service-defaults"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "namespace", "namespace2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "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.1485775592.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + 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"), ), }, }, @@ -145,7 +145,7 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { // Destination and Upstream Config are exlusive. const testConsulServiceDefaultsConfigEntryWithDestinationEE = ` -resource "consul_service_defaults_config_entry" "foo" { +resource "consul_config_entry_service_defaults" "foo" { name = "service-defaults-test-1" namespace = "namespace1" partition = "partition1" @@ -203,7 +203,7 @@ resource "consul_service_defaults_config_entry" "foo" { ` const testConsulServiceDefaultsConfigEntryWithUpstreamConfigEE = ` -resource "consul_service_defaults_config_entry" "bar" { +resource "consul_config_entry_service_defaults" "bar" { name = "service-defaults-test-2" namespace = "namespace2" partition = "partition2" From 7ba2e438c771be61a47c863e17f937543a99a6a3 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 15:42:30 +0530 Subject: [PATCH 36/89] added len check --- ...ce_consul_config_entry_service_defaults.go | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 95402b13..bd00c650 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -477,26 +477,29 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} - upstreamConfigMap := d.Get("upstream_config").(*schema.Set).List()[0].(map[string]interface{}) - defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() - if len(defaultsUpstreamConfigMapList) > 0 { - defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) - if err != nil { - return nil, err + upstreamConfigList := d.Get("upstream_config").(*schema.Set).List() + if len(upstreamConfigList) > 1 { + upstreamConfigMap := upstreamConfigList[0].(map[string]interface{}) + defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() + if len(defaultsUpstreamConfigMapList) > 0 { + defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) + if err != nil { + return nil, err + } + configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig } - configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig - } - overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) - var overrideUpstreamConfig []*consulapi.UpstreamConfig - for _, elem := range overrideUpstreamConfigList { - overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) - if err != nil { - return nil, err + overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) + var overrideUpstreamConfig []*consulapi.UpstreamConfig + for _, elem := range overrideUpstreamConfigList { + overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) + if err != nil { + return nil, err + } + overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) } - overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) + configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig } - configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig transparentProxyList := d.Get("transparent_proxy").(*schema.Set).List() if len(transparentProxyList) > 0 { From d8b0bef5ebbd12de448c8fc7f09b2d865d72bae6 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 15:55:11 +0530 Subject: [PATCH 37/89] fix nil checks and tests --- ...ce_consul_config_entry_service_defaults.go | 44 +++++++++++-------- ...l_config_entry_service_defaults_ce_test.go | 2 - ...l_config_entry_service_defaults_ee_test.go | 2 - 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index bd00c650..2ff4698e 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -449,10 +449,17 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } getDestination := func(destinationMap map[string]interface{}) *consulapi.DestinationConfig { - var destination consulapi.DestinationConfig - destination.Port = destinationMap["port"].(int) - destination.Addresses = destinationMap["addresses"].([]string) - return &destination + if destinationMap != nil { + var destination consulapi.DestinationConfig + destination.Port = destinationMap["port"].(int) + addresess := make([]string, len(destinationMap["addresses"].([]interface{}))) + for indx, address := range destinationMap["addresses"].([]interface{}) { + addresess[indx] = address.(string) + } + destination.Addresses = addresess + return &destination + } + return nil } getExposePath := func(exposePathMap map[string]interface{}) *consulapi.ExposePath { @@ -475,10 +482,9 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return exposeConfig } - configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} - upstreamConfigList := d.Get("upstream_config").(*schema.Set).List() if len(upstreamConfigList) > 1 { + configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} upstreamConfigMap := upstreamConfigList[0].(map[string]interface{}) defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() if len(defaultsUpstreamConfigMapList) > 0 { @@ -592,19 +598,21 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error return upstreamConfig } - var overrides []interface{} - for _, elem := range sp.UpstreamConfig.Overrides { - overrides = append(overrides, getUpstreamConfig(elem)) - } + if sp.UpstreamConfig != nil { + var overrides []interface{} + for _, elem := range sp.UpstreamConfig.Overrides { + overrides = append(overrides, getUpstreamConfig(elem)) + } - upstreamConfig := make(map[string]interface{}) - upstreamConfig["overrides"] = overrides - defaultsSlice := make([]map[string]interface{}, 1) - defaultsSlice[0] = getUpstreamConfig(sp.UpstreamConfig.Defaults) - upstreamConfig["defaults"] = defaultsSlice - upstreamConfigSlice := make([]map[string]interface{}, 1) - upstreamConfigSlice[0] = upstreamConfig - sw.set("upstream_config", upstreamConfigSlice) + upstreamConfig := make(map[string]interface{}) + upstreamConfig["overrides"] = overrides + defaultsSlice := make([]map[string]interface{}, 1) + defaultsSlice[0] = getUpstreamConfig(sp.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{}) diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go index 09f2e7eb..910479e2 100644 --- a/consul/resource_consul_config_entry_service_defaults_ce_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -19,7 +19,6 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { 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", "kind", "service-defaults"), 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"), @@ -60,7 +59,6 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { 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", "kind", "service-defaults"), 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"), diff --git a/consul/resource_consul_config_entry_service_defaults_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go index 385b4da9..f804a659 100644 --- a/consul/resource_consul_config_entry_service_defaults_ee_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ee_test.go @@ -19,7 +19,6 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { 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", "kind", "service-defaults"), 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"), @@ -62,7 +61,6 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { 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", "kind", "service-defaults"), resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "namespace", "namespace2"), resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "partition", "partition2"), resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "meta.key", "value"), From 832327b1cc83b9178f99b9b5cd40b90f1d3fbfc5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 16:09:43 +0530 Subject: [PATCH 38/89] removed helper go --- consul/helper.go | 77 ------------------------------------------- consul/helper_test.go | 41 ----------------------- go.mod | 5 +-- go.sum | 2 -- 4 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 consul/helper.go delete mode 100644 consul/helper_test.go diff --git a/consul/helper.go b/consul/helper.go deleted file mode 100644 index 3735003b..00000000 --- a/consul/helper.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "golang.org/x/text/cases" - "golang.org/x/text/language" - "reflect" - "strings" -) - -func isSlice(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array -} - -func isMap(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Map -} - -func isSetSchema(v interface{}) bool { - return reflect.TypeOf(v).String() == "*schema.Set" -} - -func formatKey(key string) string { - tokens := strings.Split(key, "_") - keyToReturn := "" - for _, token := range tokens { - if token == "tls" { - keyToReturn += strings.ToUpper(token) - } else { - caser := cases.Title(language.English) - keyToReturn += caser.String(token) - } - } - return keyToReturn -} - -func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { - if isMap(config) { - formattedMap := make(map[string]interface{}) - for key, value := range config.(map[string]interface{}) { - formattedKey := formatFunc(key) - formattedValue, err := formatKeys(value, formatKey) - if err != nil { - return nil, err - } - if formattedValue != nil { - formattedMap[formattedKey] = formattedValue - } - } - return formattedMap, nil - } else if isSlice(config) { - var newSlice []interface{} - listValue := config.([]interface{}) - for _, elem := range listValue { - newElem, err := formatKeys(elem, formatKey) - if err != nil { - return nil, err - } - newSlice = append(newSlice, newElem) - } - return newSlice, nil - } else if isSetSchema(config) { - valueList := config.(*schema.Set).List() - if len(valueList) > 0 { - formattedSetValue, err := formatKeys(valueList[0], formatKey) - if err != nil { - return nil, err - } - return formattedSetValue, nil - } - return nil, nil - } - return config, nil -} diff --git a/consul/helper_test.go b/consul/helper_test.go deleted file mode 100644 index 92705df8..00000000 --- a/consul/helper_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package consul - -import ( - "bytes" - "fmt" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/stretchr/testify/require" - "testing" -) - -func TestFormatKeysFunc(t *testing.T) { - dummySetSchema := new(schema.Set) - dummySetSchema.F = func(i interface{}) int { - var buf bytes.Buffer - buf.WriteString(fmt.Sprintf("%s-", i)) - return hashcode.String(buf.String()) - } - dummySetSchema.Add(map[string]interface{}{"test_set_key": "test_value"}) - dataSet := []map[string]interface{}{ - { - "input": map[string]interface{}{ - "test_key": "value1", - "test_tls_key": "value2", - }, - "expected": map[string]interface{}{ - "TestKey": "value1", - "TestTLSKey": "value2", - }, - }, - { - "input": dummySetSchema, - "expected": map[string]interface{}{"TestSetKey": "test_value"}, - }, - } - for _, testCase := range dataSet { - res, err := formatKeys(testCase["input"], formatKey) - require.NoError(t, err) - require.Equal(t, testCase["expected"], res) - } -} diff --git a/go.mod b/go.mod index b27e07c9..df391ba3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ require ( github.com/hashicorp/errwrap v1.1.0 github.com/hashicorp/terraform-plugin-sdk v1.17.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/stretchr/testify v1.8.3 ) require ( @@ -13,9 +12,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v0.12.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( @@ -94,7 +91,7 @@ require ( golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 + golang.org/x/text v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.114.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 093d0fe6..f704096c 100644 --- a/go.sum +++ b/go.sum @@ -601,7 +601,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= @@ -653,7 +652,6 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= From 4e5d6f91df8ac9af689f42a0a3baadc570d20a4f Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 16:20:37 +0530 Subject: [PATCH 39/89] nil check --- consul/resource_consul_config_entry_service_defaults.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 2ff4698e..9be74709 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -533,7 +533,10 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, configEntry.MaxInboundConnections = d.Get("max_inbound_connections").(int) configEntry.LocalRequestTimeoutMs = d.Get("local_request_timeout_ms").(int) - configEntry.MeshGateway = *getMeshGateway(d.Get("mesh_gateway")) + if v := getMeshGateway(d.Get("mesh_gateway")); v != nil { + configEntry.MeshGateway = *v + } + configEntry.ExternalSNI = d.Get("external_sni").(string) exposeList := d.Get("expose").(*schema.Set).List() From 86ae20482bb13a8a53d968558f2f35168b58dd55 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 16:43:27 +0530 Subject: [PATCH 40/89] added description --- ...ce_consul_config_entry_service_defaults.go | 123 ++++++++++-------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 9be74709..24cbd6fa 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -32,12 +32,14 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { Optional: true, }, "namespace": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the namespace containing the upstream service that the configuration applies to.", }, "peer": { - Type: schema.TypeString, - Optional: true, + 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, @@ -122,75 +124,79 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, } return map[string]*schema.Schema{ - "kind": { - Type: schema.TypeString, - Required: false, - ForceNew: true, - Computed: true, - }, "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + 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, + 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: "The partition the config entry is associated with.", + 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}, + 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, + Type: schema.TypeString, + Required: true, + Description: "Specifies the default protocol for the service.", }, "balance_inbound_connections": { - Type: schema.TypeString, - Optional: true, + 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, + 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, + 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: upstreamConfigSchema, + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchema, + Description: "Specifies options that override the default upstream configurations for individual upstreams.", }, "defaults": { - Type: schema.TypeSet, - Optional: true, - Elem: upstreamConfigSchema, + Type: schema.TypeSet, + Optional: true, + Elem: upstreamConfigSchema, + 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, + 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": { @@ -206,13 +212,15 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, "mutual_tls_mode": { - Type: schema.TypeString, - Optional: true, + 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, + Type: schema.TypeList, + Optional: true, + Description: "List of extensions to modify Envoy proxy configuration.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -241,8 +249,9 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, "destination": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeSet, + Optional: true, + Description: "Configures the destination for service traffic through terminating gateways.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "port": { @@ -259,23 +268,27 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, "local_connect_timeout_ms": { - Type: schema.TypeInt, - Optional: true, + 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, + 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, + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the timeout for HTTP requests to the local application instance.", }, "mesh_gateway": { - Type: schema.TypeSet, - Optional: true, + 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": { @@ -287,13 +300,15 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, "external_sni": { - Type: schema.TypeString, - Optional: true, + 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, + Type: schema.TypeSet, + Required: true, + Description: "Specifies default configurations for exposing HTTP paths through Envoy.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "checks": { From 4d6a00a196fb93578323d4da3a16b298b2f4ff85 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 18:04:29 +0530 Subject: [PATCH 41/89] add description fields --- ...ce_consul_config_entry_service_defaults.go | 75 +++++++++++-------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 24cbd6fa..1203184a 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -24,12 +24,14 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { upstreamConfigSchema := &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of the service you are setting the defaults for.", }, "partition": { - Type: schema.TypeString, - Optional: true, + 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, @@ -50,64 +52,76 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { Optional: true, }, "protocol": { - Type: schema.TypeString, - Optional: true, + 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, + 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, + 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, + 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, + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of concurrent requests.", }, }, }, }, "passive_health_check": { - Type: schema.TypeSet, - Optional: true, + 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, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the time between checks.", }, "max_failures": { - Type: schema.TypeInt, - Optional: true, + 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, + 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, + 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, + 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, + 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": { @@ -118,8 +132,9 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, "balance_outbound_connections": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads.", }, }, } From c5dd53a30c868b3979079ee5ffc087bcac45b557 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 20:38:38 +0530 Subject: [PATCH 42/89] decode --- ...ce_consul_service_resolver_config_entry.go | 753 +++++++++--------- consul/resource_provider.go | 1 + 2 files changed, 377 insertions(+), 377 deletions(-) diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 988bbae2..536054b3 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -4,435 +4,434 @@ package consul import ( - "fmt" - "strings" - "time" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "time" ) -const KindServiceResolver = "service-resolver" +type serviceResolver struct{} -var serviceResolverConfigEntrySchema = map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "kind": { - Type: schema.TypeString, - Required: false, - ForceNew: true, - Computed: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "meta": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "connect_timeout": { - Type: schema.TypeString, - Optional: true, - }, - "request_timeout": { - Type: schema.TypeString, - Optional: true, - }, - "subsets": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "filter": { - Type: schema.TypeString, - Required: true, - }, - "only_passing": { - Type: schema.TypeBool, - Required: true, +func (s *serviceResolver) GetKind() string { + return consulapi.ServiceResolver +} + +func (s *serviceResolver) GetSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Specifies a name for the configuration entry.", + }, + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Specifies the admin partition that the service resolver applies to.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Specifies the namespace that the service resolver applies to.", + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Specifies key-value pairs to add to the KV store.", + }, + "connect_timeout": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the timeout duration for establishing new network connections to this service.", + }, + "request_timeout": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the timeout duration for receiving an HTTP response from this service.", + }, + "subsets": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies names for custom service subsets and the conditions under which service instances belong to each subset.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Name of subset", + }, + "filter": { + Type: schema.TypeString, + Required: true, + Description: "Specifies an expression that filters the DNS elements of service instances that belong to the subset. If empty, all healthy instances of a service are returned.", + }, + "only_passing": { + Type: schema.TypeBool, + Required: true, + Description: "Determines if instances that return a warning from a health check are allowed to resolve a request. When set to false, instances with passing and warning states are considered healthy. When set to true, only instances with a passing health check state are considered healthy.", + }, }, }, }, - }, - "default_subset": { - Type: schema.TypeString, - Optional: true, - }, - "redirect": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "service": { - Type: schema.TypeString, - Optional: true, - }, - "service_subset": { - Type: schema.TypeString, - Optional: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - }, - "sameness_group": { - Type: schema.TypeString, - Optional: true, - }, - "datacenter": { - Type: schema.TypeString, - Optional: true, - }, - "peer": { - Type: schema.TypeString, - Optional: true, + "default_subset": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a defined subset of service instances to use when no explicit subset is requested. If this parameter is not specified, Consul uses the unnamed default subset.", + }, + "redirect": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies redirect instructions for local service traffic so that services deployed to a different network location resolve the upstream request instead.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of a service at the redirect’s destination that resolves local upstream requests.", + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of a subset of services at the redirect’s destination that resolves local upstream requests. If empty, the default subset is used. If specified, you must also specify at least one of the following in the same Redirect map: Service, Namespace, andDatacenter.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the namespace at the redirect’s destination that resolves local upstream requests.", + }, + "partition": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the admin partition at the redirect’s destination that resolves local upstream requests.", + }, + "sameness_group": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the sameness group at the redirect’s destination that resolves local upstream requests.", + }, + "datacenter": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the datacenter at the redirect’s destination that resolves local upstream requests.", + }, + "peer": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the cluster with an active cluster peering connection at the redirect’s destination that resolves local upstream requests.", + }, }, }, }, - }, - "failover": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "subset_name": { - Type: schema.TypeString, - Required: true, - }, - "service": { - Type: schema.TypeString, - Optional: true, - }, - "service_subset": { - Type: schema.TypeString, - Optional: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - "sameness_group": { - Type: schema.TypeString, - Optional: true, - }, - "datacenters": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "targets": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "service": { - Type: schema.TypeString, - Optional: true, - }, - "service_subset": { - Type: schema.TypeString, - Optional: true, - }, - "namespace": { - Type: schema.TypeString, - Optional: true, - }, - "partition": { - Type: schema.TypeString, - Optional: true, - }, - "datacenter": { - Type: schema.TypeString, - Optional: true, - }, - "peer": { - Type: schema.TypeString, - Optional: true, + "failover": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies controls for rerouting traffic to an alternate pool of service instances if the target service fails.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subset_name": { + Type: schema.TypeString, + Required: true, + Description: "Name of subset", + }, + "service": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of the service to resolve at the failover location during a failover scenario.", + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of a subset of service instances to resolve at the failover location during a failover scenario.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the namespace at the failover location where the failover services are deployed.", + }, + "sameness_group": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the sameness group at the failover location where the failover services are deployed.", + }, + "datacenters": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Specifies an ordered list of datacenters at the failover location to attempt connections to during a failover scenario. When Consul cannot establish a connection with the first datacenter in the list, it proceeds sequentially until establishing a connection with another datacenter.", + }, + "targets": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies a fixed list of failover targets to try during failover. This list can express complicated failover scenarios.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the service name to use for the failover target. If empty, the current service name is used.", + }, + "service_subset": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the named subset to use for the failover target. If empty, the default subset for the requested service name is used.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the namespace to use for the failover target. If empty, the default namespace is used.", + }, + "partition": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the admin partition within the same datacenter to use for the failover target. If empty, the default partition is used.", + }, + "datacenter": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the WAN federated datacenter to use for the failover target. If empty, the current datacenter is used.", + }, + "peer": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the destination cluster peer to resolve the target service name from.", + }, }, }, }, }, }, }, - }, - "load_balancer": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "policy": { - Type: schema.TypeString, - Optional: true, - }, - "least_request_config": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "choice_count": { - Type: schema.TypeInt, - Optional: true, + "load_balancer": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies the load balancing policy and configuration for services issuing requests to this upstream.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the type of load balancing policy for selecting a host. ", + }, + "least_request_config": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies configuration for the least_request policy type.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "choice_count": { + Type: schema.TypeInt, + Optional: true, + }, }, }, }, - }, - "ring_hash_config": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "minimum_ring_size": { - Type: schema.TypeInt, - Optional: true, - }, - "maximum_ring_size": { - Type: schema.TypeInt, - Optional: true, + "ring_hash_config": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies configuration for the ring_hash policy type.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "minimum_ring_size": { + Type: schema.TypeInt, + Optional: true, + Description: "Determines the minimum number of entries in the hash ring.", + }, + "maximum_ring_size": { + Type: schema.TypeInt, + Optional: true, + Description: "Determines the maximum number of entries in the hash ring.", + }, }, }, }, - }, - "hash_policies": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "field": { - Type: schema.TypeString, - Optional: true, - }, - "field_value": { - Type: schema.TypeString, - Optional: true, - }, - "cookie_config": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "session": { - Type: schema.TypeBool, - Optional: true, - }, - "ttl": { - Type: schema.TypeString, - Optional: true, - }, - "path": { - Type: schema.TypeString, - Optional: true, + "hash_policies": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies a list of hash policies to use for hashing load balancing algorithms. Consul evaluates hash policies individually and combines them so that identical lists result in the same hash.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the attribute type to hash on. You cannot specify the Field parameter if SourceIP is also configured.", + }, + "field_value": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the value to hash, such as a header name, cookie name, or a URL query parameter name.", + }, + "cookie_config": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies additional configuration options for the cookie hash policy type.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "session": { + Type: schema.TypeBool, + Optional: true, + Description: "Directs Consul to generate a session cookie with no expiration.", + }, + "ttl": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the TTL for generated cookies. Cannot be specified for session cookies.", + }, + "path": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the path to set for the cookie.", + }, }, }, }, - }, - "source_ip": { - Type: schema.TypeBool, - Optional: true, - }, - "terminal": { - Type: schema.TypeBool, - Optional: true, + "source_ip": { + Type: schema.TypeBool, + Optional: true, + Description: "Determines if the hash type should be source IP address.", + }, + "terminal": { + Type: schema.TypeBool, + Optional: true, + Description: "Determines if Consul should stop computing the hash when multiple hash policies are present.", + }, }, }, }, }, }, }, - }, -} - -func resourceServiceResolverConfigEntry() *schema.Resource { - - return &schema.Resource{ - Create: resourceConsulServiceResolverConfigEntryUpdate, - Update: resourceConsulServiceResolverConfigEntryUpdate, - Read: resourceConsulServiceResolverConfigEntryRead, - Delete: resourceConsulServiceResolverConfigEntryDelete, - Importer: &schema.ResourceImporter{ - State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - parts := strings.Split(d.Id(), "/") - var kind, name, partition, namespace string - switch len(parts) { - case 2: - kind = parts[0] - name = parts[1] - case 4: - partition = parts[0] - namespace = parts[1] - kind = parts[2] - name = parts[3] - default: - return nil, fmt.Errorf(`expected path of the form "/" or "///"`) - } - - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - sw := newStateWriter(d) - sw.set("kind", kind) - sw.set("name", name) - sw.set("partition", partition) - sw.set("namespace", namespace) - - err := sw.error() - if err != nil { - return nil, err - } - - return []*schema.ResourceData{d}, nil - }, - }, - Schema: serviceResolverConfigEntrySchema, } } -func resourceConsulServiceResolverConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { - client, qOpts, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - - name := d.Get("name").(string) - - configMap := make(map[string]interface{}) - configMap["kind"] = KindServiceResolver - - configMap["name"] = name - - kind := configMap["kind"].(string) - err := d.Set("kind", kind) - - if err != nil { - return err - } - - var attributes []string - - for key, _ := range serviceResolverConfigEntrySchema { - attributes = append(attributes, key) +func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { + configEntry := &consulapi.ServiceResolverConfigEntry{ + Kind: consulapi.ServiceResolver, + Name: d.Get("name").(string), + Partition: d.Get("partition").(string), + Namespace: d.Get("namespace").(string), + Meta: map[string]string{}, } - for _, attribute := range attributes { - if attribute == "failover" { - value := d.Get(attribute) - failover := make(map[string]interface{}) - for _, elem := range value.([]interface{}) { - valueMap := elem.(map[string]interface{}) - key := valueMap["subset_name"].(string) - delete(valueMap, "subset_name") - formattedValueMap, err := formatKeys(valueMap, formatKey) - if err != nil { - return err - } - failover[key] = formattedValueMap - } - if err != nil { - return err - } - configMap["failover"] = failover - } else if attribute == "subsets" { - value := d.Get(attribute) - subsets := make(map[string]interface{}) - for _, elem := range value.([]interface{}) { - valueMap := elem.(map[string]interface{}) - key := valueMap["name"].(string) - delete(valueMap, "name") - formattedValueMap, err := formatKeys(valueMap, formatKey) - if err != nil { - return err - } - subsets[key] = formattedValueMap - } - if err != nil { - return err - } - configMap["subsets"] = subsets - } else if attribute == "request_timeout" || attribute == "connect_timeout" { - duration, err := time.ParseDuration(d.Get(attribute).(string)) - if err != nil { - return err - } - configMap[formatKey(attribute)] = duration - } else { - keyFormattedMap, err := formatKeys(d.Get(attribute), formatKey) - if err != nil { - return err - } - configMap[formatKey(attribute)] = keyFormattedMap - } + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) } - configEntry, err := makeServiceResolverConfigEntry(name, configMap, wOpts.Namespace, wOpts.Partition) + connectTimeout, err := time.ParseDuration(d.Get("connect_timeout").(string)) if err != nil { - return err + return nil, err } + configEntry.ConnectTimeout = connectTimeout - if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { - return fmt.Errorf("failed to set '%s' config entry: %v", name, err) - } - _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) + requestTimeout, err := time.ParseDuration(d.Get("connect_timeout").(string)) if err != nil { - if strings.Contains(err.Error(), "Unexpected response code: 404") { - return fmt.Errorf(`failed to read config entry after setting it. -This may happen when some attributes have an unexpected value. -Read the documentation at https://www.consul.io/docs/agent/config-entries/%s.html -to see what values are expected`, configEntry.GetKind()) - } - return fmt.Errorf("failed to read config entry: %v", err) + return nil, err } + configEntry.RequestTimeout = requestTimeout - d.SetId(fmt.Sprintf("%s-%s", kind, name)) - return resourceConsulServiceResolverConfigEntryRead(d, meta) -} - -func resourceConsulServiceResolverConfigEntryRead(d *schema.ResourceData, meta interface{}) error { - client, qOpts, _ := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) + subsets := make(map[string]consulapi.ServiceResolverSubset) - _, _, err := configEntries.Get(configKind, configName, qOpts) - return err -} + subsetsList := d.Get("subsets").([]interface{}) + for _, subset := range subsetsList { + subsetMap := subset.(map[string]interface{}) + var serviceResolverSubset consulapi.ServiceResolverSubset + serviceResolverSubset.Filter = subsetMap["filter"].(string) + serviceResolverSubset.OnlyPassing = subsetMap["only_passing"].(bool) + subsets[subsetMap["name"].(string)] = serviceResolverSubset + } + configEntry.Subsets = subsets -func resourceConsulServiceResolverConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { - client, _, wOpts := getClient(d, meta) - configEntries := client.ConfigEntries() - configKind := d.Get("kind").(string) - configName := d.Get("name").(string) + configEntry.DefaultSubset = d.Get("default_subset").(string) - if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { - return fmt.Errorf("failed to delete '%s' config entry: %v", configName, err) + if v := (d.Get("redirect").(*schema.Set)).List(); len(v) == 1 { + redirectMap := v[0].(map[string]interface{}) + var serviceResolverRedirect *consulapi.ServiceResolverRedirect + serviceResolverRedirect = new(consulapi.ServiceResolverRedirect) + serviceResolverRedirect.Service = redirectMap["service"].(string) + serviceResolverRedirect.ServiceSubset = redirectMap["service_subset"].(string) + serviceResolverRedirect.Namespace = redirectMap["namespace"].(string) + serviceResolverRedirect.Partition = redirectMap["partition"].(string) + serviceResolverRedirect.SamenessGroup = redirectMap["sameness_group"].(string) + serviceResolverRedirect.Datacenter = redirectMap["datacenter"].(string) + serviceResolverRedirect.Peer = redirectMap["peer"].(string) + configEntry.Redirect = serviceResolverRedirect } - d.SetId("") - return nil -} -func makeServiceResolverConfigEntry(name string, configMap map[string]interface{}, namespace, partition string) (consulapi.ConfigEntry, error) { - configMap["kind"] = KindServiceResolver - configMap["name"] = name - configMap["Namespace"] = namespace - configMap["Partition"] = partition + failoverList := d.Get("failover").([]interface{}) + failover := make(map[string]consulapi.ServiceResolverFailover) + for _, failoverElem := range failoverList { + failoverMap := failoverElem.(map[string]interface{}) + var serviceResolverFailover consulapi.ServiceResolverFailover + serviceResolverFailover.Service = failoverMap["service"].(string) + serviceResolverFailover.ServiceSubset = failoverMap["service_subset"].(string) + serviceResolverFailover.Namespace = failoverMap["namespace"].(string) + serviceResolverFailover.SamenessGroup = failoverMap["sameness_group"].(string) + serviceResolverFailover.Datacenters = failoverMap["datacenter"].([]string) + serviceResolverFailoverTargets := make([]consulapi.ServiceResolverFailoverTarget, len(failoverMap["targets"].([]interface{}))) + for indx, targetElem := range failoverMap["targets"].([]map[string]interface{}) { + var serviceResolverFailoverTarget consulapi.ServiceResolverFailoverTarget + serviceResolverFailoverTarget.Service = targetElem["service"].(string) + serviceResolverFailoverTarget.ServiceSubset = targetElem["service_subset"].(string) + serviceResolverFailoverTarget.Namespace = targetElem["namespace"].(string) + serviceResolverFailoverTarget.Partition = targetElem["partition"].(string) + serviceResolverFailoverTarget.Datacenter = targetElem["datacenter"].(string) + serviceResolverFailoverTarget.Peer = targetElem["peer"].(string) + serviceResolverFailoverTargets[indx] = serviceResolverFailoverTarget + } + serviceResolverFailover.Targets = serviceResolverFailoverTargets + failover[failoverMap["subset_name"].(string)] = serviceResolverFailover + } + configEntry.Failover = failover - configEntry, err := consulapi.DecodeConfigEntry(configMap) - if err != nil { - return nil, fmt.Errorf("failed to decode config entry: %v", err) + if lb := (d.Get("load_balancer").(*schema.Set)).List(); len(lb) == 1 { + loadBalancer := lb[0].(map[string]interface{}) + var ceLoadBalancer *consulapi.LoadBalancer + ceLoadBalancer = new(consulapi.LoadBalancer) + ceLoadBalancer.Policy = loadBalancer["policy"].(string) + if lrc := (loadBalancer["least_request_config"].(*schema.Set)).List(); len(lrc) == 1 { + var lreqConfig *consulapi.LeastRequestConfig + lreqConfig = new(consulapi.LeastRequestConfig) + lreqConfig.ChoiceCount = uint32(((lrc[0].(map[string]interface{}))["choice_count"]).(int)) + ceLoadBalancer.LeastRequestConfig = lreqConfig + } + if rhc := (loadBalancer["ring_hash_config"].(*schema.Set)).List(); len(rhc) == 1 { + var rhConfig *consulapi.RingHashConfig + rhConfig = new(consulapi.RingHashConfig) + rhConfig.MaximumRingSize = uint64(rhc[0].(map[string]interface{})["maximum_ring_size"].(int)) + rhConfig.MinimumRingSize = uint64(rhc[0].(map[string]interface{})["minimum_ring_size"].(int)) + ceLoadBalancer.RingHashConfig = rhConfig + } + if hp := loadBalancer["hash_policies"].([]interface{}); len(hp) > 0 { + var hashPolicyList []consulapi.HashPolicy + for indx, hashPolicy := range hp { + hashPolicyMap := hashPolicy.(map[string]interface{}) + hashPolicyList[indx].Field = hashPolicyMap["field"].(string) + hashPolicyList[indx].FieldValue = hashPolicyMap["field_value"].(string) + var cookieConfig *consulapi.CookieConfig + cookieConfig = new(consulapi.CookieConfig) + if cc := hashPolicyMap["cookie_config"].(*schema.Set).List(); len(cc) == 1 { + cookieConfigMap := cc[0].(map[string]interface{}) + cookieConfig.Path = cookieConfigMap["path"].(string) + cookieConfig.Session = cookieConfigMap["session"].(bool) + ttl, err := time.ParseDuration(cookieConfigMap["ttl"].(string)) + if err != nil { + return nil, err + } + cookieConfig.TTL = ttl + hashPolicyList[indx].CookieConfig = cookieConfig + } + hashPolicyList[indx].SourceIP = hashPolicyMap["source_ip"].(bool) + hashPolicyList[indx].Terminal = hashPolicyMap["terminal"].(bool) + } + ceLoadBalancer.HashPolicies = hashPolicyList + } + configEntry.LoadBalancer = ceLoadBalancer } return configEntry, nil } + +func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { + +} diff --git a/consul/resource_provider.go b/consul/resource_provider.go index c32e164b..b54ad9b8 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -239,6 +239,7 @@ func Provider() terraform.ResourceProvider { "consul_certificate_authority": resourceConsulCertificateAuthority(), "consul_config_entry_service_splitter": resourceFromConfigEntryImplementation(&serviceSplitter{}), "consul_config_entry_service_defaults": resourceFromConfigEntryImplementation(&serviceDefaults{}), + "consul_config_entry_service_resolver": resourceFromConfigEntryImplementation(&serviceResolver{}), "consul_config_entry": resourceConsulConfigEntry(), "consul_intention": resourceConsulIntention(), "consul_key_prefix": resourceConsulKeyPrefix(), From c1d8271d6e5471981a97236879e86cc25e03bea4 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 20:41:24 +0530 Subject: [PATCH 43/89] init write --- ...urce_consul_service_resolver_config_entry.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 536054b3..89491b65 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -4,6 +4,7 @@ package consul import ( + "fmt" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "time" @@ -433,5 +434,21 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { + sr, ok := ce.(*consulapi.ServiceResolverConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceResolver, ce.GetKind()) + } + + sw.set("name", sr.Name) + sw.set("partition", sr.Partition) + sw.set("namespace", sr.Namespace) + + meta := map[string]interface{}{} + for k, v := range sr.Meta { + meta[k] = v + } + sw.set("meta", meta) + sw.set("connect_timeout", sr.ConnectTimeout) + return nil } From 8ffb8a8984f6eb91223fedc49f769aaa91a5232e Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 20:42:20 +0530 Subject: [PATCH 44/89] rename var name --- ...ce_consul_config_entry_service_defaults.go | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 1203184a..794ebbfd 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -578,24 +578,24 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { - sp, ok := ce.(*consulapi.ServiceConfigEntry) + sd, ok := ce.(*consulapi.ServiceConfigEntry) if !ok { return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceDefaults, ce.GetKind()) } - sw.set("name", sp.Name) - sw.set("partition", sp.Partition) - sw.set("namespace", sp.Partition) + sw.set("name", sd.Name) + sw.set("partition", sd.Partition) + sw.set("namespace", sd.Partition) meta := make(map[string]interface{}) - for k, v := range sp.Meta { + for k, v := range sd.Meta { meta[k] = v } sw.set("meta", meta) - sw.set("protocol", sp.Protocol) - sw.set("balance_inbound_connections", sp.BalanceInboundConnections) - sw.set("mode", sp.Mode) + sw.set("protocol", sd.Protocol) + sw.set("balance_inbound_connections", sd.BalanceInboundConnections) + sw.set("mode", sd.Mode) getUpstreamConfig := func(elem *consulapi.UpstreamConfig) map[string]interface{} { upstreamConfig := make(map[string]interface{}) @@ -631,16 +631,16 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error return upstreamConfig } - if sp.UpstreamConfig != nil { + if sd.UpstreamConfig != nil { var overrides []interface{} - for _, elem := range sp.UpstreamConfig.Overrides { + for _, elem := range sd.UpstreamConfig.Overrides { overrides = append(overrides, getUpstreamConfig(elem)) } upstreamConfig := make(map[string]interface{}) upstreamConfig["overrides"] = overrides defaultsSlice := make([]map[string]interface{}, 1) - defaultsSlice[0] = getUpstreamConfig(sp.UpstreamConfig.Defaults) + defaultsSlice[0] = getUpstreamConfig(sd.UpstreamConfig.Defaults) upstreamConfig["defaults"] = defaultsSlice upstreamConfigSlice := make([]map[string]interface{}, 1) upstreamConfigSlice[0] = upstreamConfig @@ -649,11 +649,11 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error transparentProxy := make([]map[string]interface{}, 1) transparentProxy[0] = make(map[string]interface{}) - transparentProxy[0]["outbound_listener_port"] = sp.TransparentProxy.OutboundListenerPort - transparentProxy[0]["dialed_directly"] = sp.TransparentProxy.DialedDirectly + 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", sp.MutualTLSMode) + sw.set("mutual_tls_mode", sd.MutualTLSMode) getEnvoyExtension := func(elem consulapi.EnvoyExtension) map[string]interface{} { envoyExtension := make(map[string]interface{}) @@ -670,35 +670,35 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } var envoyExtensions []map[string]interface{} - for _, elem := range sp.EnvoyExtensions { + for _, elem := range sd.EnvoyExtensions { envoyExtensions = append(envoyExtensions, getEnvoyExtension(elem)) } sw.set("envoy_extensions", envoyExtensions) destination := make([]map[string]interface{}, 1) - if sp.Destination != nil { + if sd.Destination != nil { destination[0] = make(map[string]interface{}) - destination[0]["port"] = sp.Destination.Port - destination[0]["addresses"] = sp.Destination.Addresses + destination[0]["port"] = sd.Destination.Port + destination[0]["addresses"] = sd.Destination.Addresses sw.set("destination", destination) } - sw.set("local_connect_timeout_ms", sp.LocalConnectTimeoutMs) - sw.set("max_inbound_connections", sp.MaxInboundConnections) - sw.set("local_request_timeout_ms", sp.LocalRequestTimeoutMs) + 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"] = sp.MeshGateway.Mode + meshGateway[0]["mode"] = sd.MeshGateway.Mode sw.set("mesh_gateway", meshGateway) - sw.set("external_sni", sp.ExternalSNI) + sw.set("external_sni", sd.ExternalSNI) expose := make([]map[string]interface{}, 1) expose[0] = make(map[string]interface{}) - expose[0]["checks"] = sp.Expose.Checks + expose[0]["checks"] = sd.Expose.Checks var paths []map[string]interface{} - for _, elem := range sp.Expose.Paths { + for _, elem := range sd.Expose.Paths { path := make(map[string]interface{}) path["path"] = elem.Path path["local_path_port"] = elem.LocalPathPort From e907aa0eb88424a9f102cefc70f5ea22cc759f50 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 21:25:19 +0530 Subject: [PATCH 45/89] write --- ...ce_consul_service_resolver_config_entry.go | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_service_resolver_config_entry.go index 89491b65..3c6a2446 100644 --- a/consul/resource_consul_service_resolver_config_entry.go +++ b/consul/resource_consul_service_resolver_config_entry.go @@ -16,6 +16,10 @@ func (s *serviceResolver) GetKind() string { return consulapi.ServiceResolver } +func (s *serviceResolver) GetDescription() string { + return "The `consul_config_entry_service_resolver` resource configures a [service resolver](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-resolver) that creates named subsets of service instances and define their behavior when satisfying upstream requests." +} + func (s *serviceResolver) GetSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ "name": { @@ -449,6 +453,105 @@ func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } sw.set("meta", meta) sw.set("connect_timeout", sr.ConnectTimeout) + sw.set("request_timeout", sr.RequestTimeout) + + subsets := make([]map[string]interface{}, len(sr.Subsets)) + indx := 0 + for name, _ := range sr.Subsets { + subsetMap := make(map[string]interface{}) + subsetMap["name"] = name + subsetSt := sr.Subsets[name] + subsetMap["filter"] = subsetSt.Filter + subsetMap["only_passing"] = subsetSt.OnlyPassing + subsets[indx] = subsetMap + indx++ + } + sw.set("subsets", subsets) + + sw.set("default_subset", sr.DefaultSubset) + + redirect := make([]map[string]interface{}, 1) + if sr.Redirect != nil { + redirect[0] = make(map[string]interface{}) + redirect[0]["service"] = sr.Redirect.Service + redirect[0]["service_subset"] = sr.Redirect.ServiceSubset + redirect[0]["namespace"] = sr.Redirect.Namespace + redirect[0]["partition"] = sr.Redirect.Partition + redirect[0]["sameness_group"] = sr.Redirect.SamenessGroup + redirect[0]["datacenter"] = sr.Redirect.Datacenter + redirect[0]["peer"] = sr.Redirect.Peer + sw.set("redirect", redirect) + } + + failover := make([]map[string]interface{}, len(sr.Failover)) + iter := 0 + for name, _ := range sr.Failover { + failoverMap := make(map[string]interface{}) + failoverMap["subset_name"] = name + failoverMap["service"] = sr.Failover[name].Service + failoverMap["service_subset"] = sr.Failover[name].ServiceSubset + failoverMap["namespace"] = sr.Failover[name].Namespace + failoverMap["sameness_group"] = sr.Failover[name].SamenessGroup + failoverDatacenters := make([]string, len(sr.Failover[name].Datacenters)) + for indx, fd := range sr.Failover[name].Datacenters { + failoverDatacenters[indx] = fd + } + failoverMap["datacenters"] = failoverDatacenters + failoverTargets := make([]map[string]interface{}, len(sr.Failover[name].Targets)) + for indx, ft := range sr.Failover[name].Targets { + failoverTargetMap := make(map[string]interface{}) + failoverTargetMap["service"] = ft.Service + failoverTargetMap["service_subset"] = ft.ServiceSubset + failoverTargetMap["namespace"] = ft.Namespace + failoverTargetMap["partition"] = ft.Partition + failoverTargetMap["datacenter"] = ft.Datacenter + failoverTargetMap["peer"] = ft.Peer + failoverTargets[indx] = failoverTargetMap + } + failoverMap["targets"] = failoverTargets + failover[iter] = failoverMap + iter++ + } + sw.set("failover", failover) + + if sr.LoadBalancer != nil { + loadBalancer := make([]map[string]interface{}, 1) + loadBalancer[0] = make(map[string]interface{}) + loadBalancer[0]["policy"] = sr.LoadBalancer.Policy + if sr.LoadBalancer.LeastRequestConfig != nil { + leastRequestConfig := make([]map[string]interface{}, 1) + leastRequestConfig[0] = make(map[string]interface{}) + leastRequestConfig[0]["choice_count"] = sr.LoadBalancer.LeastRequestConfig.ChoiceCount + loadBalancer[0]["least_request_config"] = leastRequestConfig + } + if sr.LoadBalancer.RingHashConfig != nil { + ringHashConfig := make([]map[string]interface{}, 1) + ringHashConfig[0] = make(map[string]interface{}) + ringHashConfig[0]["minimum_ring_size"] = sr.LoadBalancer.RingHashConfig.MinimumRingSize + ringHashConfig[0]["maximum_ring_size"] = sr.LoadBalancer.RingHashConfig.MaximumRingSize + loadBalancer[0]["ring_hash_config"] = ringHashConfig + } + + if sr.LoadBalancer.HashPolicies != nil { + hashPolicyList := make([]map[string]interface{}, len(sr.LoadBalancer.HashPolicies)) + for indx, hashPolicy := range sr.LoadBalancer.HashPolicies { + hashPolicyMap := make(map[string]interface{}) + hashPolicyMap["field"] = hashPolicy.Field + hashPolicyMap["field_value"] = hashPolicy.FieldValue + cookieConfigSet := make([]map[string]interface{}, 1) + cookieConfigSet[0] = make(map[string]interface{}) + cookieConfigSet[0]["session"] = hashPolicy.CookieConfig.Session + cookieConfigSet[0]["ttl"] = hashPolicy.CookieConfig.TTL + cookieConfigSet[0]["path"] = hashPolicy.CookieConfig.TTL + hashPolicyMap["cookie_config"] = cookieConfigSet + hashPolicyMap["source_ip"] = hashPolicy.SourceIP + hashPolicyMap["terminal"] = hashPolicy.Terminal + hashPolicyList[indx] = hashPolicyMap + } + loadBalancer[0]["hash_policies"] = hashPolicyList + } + sw.set("load_balancer", loadBalancer) + } return nil } From f9385ffc117e892b763dd0c914d4ed12d6677e0f Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Thu, 28 Sep 2023 21:26:42 +0530 Subject: [PATCH 46/89] delete helper --- consul/helper.go | 77 ------------------------------------------- consul/helper_test.go | 45 ------------------------- 2 files changed, 122 deletions(-) delete mode 100644 consul/helper.go delete mode 100644 consul/helper_test.go diff --git a/consul/helper.go b/consul/helper.go deleted file mode 100644 index 5b63c9e1..00000000 --- a/consul/helper.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package consul - -import ( - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "golang.org/x/text/cases" - "golang.org/x/text/language" - "reflect" - "strings" -) - -func isSlice(v interface{}) bool { - return v != nil && (reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array) -} - -func isMap(v interface{}) bool { - return v != nil && reflect.TypeOf(v).Kind() == reflect.Map -} - -func isSetSchema(v interface{}) bool { - return v != nil && reflect.TypeOf(v).String() == "*schema.Set" -} - -func formatKey(key string) string { - tokens := strings.Split(key, "_") - keyToReturn := "" - for _, token := range tokens { - if token == "tls" || token == "ttl" || token == "ip" { - keyToReturn += strings.ToUpper(token) - } else { - caser := cases.Title(language.English) - keyToReturn += caser.String(token) - } - } - return keyToReturn -} - -func formatKeys(config interface{}, formatFunc func(string) string) (interface{}, error) { - if isMap(config) { - formattedMap := make(map[string]interface{}) - for key, value := range config.(map[string]interface{}) { - formattedKey := formatFunc(key) - formattedValue, err := formatKeys(value, formatKey) - if err != nil { - return nil, err - } - if formattedValue != nil { - formattedMap[formattedKey] = formattedValue - } - } - return formattedMap, nil - } else if isSlice(config) { - var newSlice []interface{} - listValue := config.([]interface{}) - for _, elem := range listValue { - newElem, err := formatKeys(elem, formatKey) - if err != nil { - return nil, err - } - newSlice = append(newSlice, newElem) - } - return newSlice, nil - } else if isSetSchema(config) { - valueList := config.(*schema.Set).List() - if len(valueList) > 0 { - formattedSetValue, err := formatKeys(valueList[0], formatKey) - if err != nil { - return nil, err - } - return formattedSetValue, nil - } - return nil, nil - } - return config, nil -} diff --git a/consul/helper_test.go b/consul/helper_test.go deleted file mode 100644 index 7a0e4348..00000000 --- a/consul/helper_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package consul - -import ( - "bytes" - "fmt" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/stretchr/testify/require" - "testing" -) - -func TestFormatKeysFunc(t *testing.T) { - dummySetSchema := new(schema.Set) - dummySetSchema.F = func(i interface{}) int { - var buf bytes.Buffer - buf.WriteString(fmt.Sprintf("%s-", i)) - return hashcode.String(buf.String()) - } - dummySetSchema.Add(map[string]interface{}{"test_set_key": "test_value"}) - dataSet := []map[string]interface{}{ - { - "input": map[string]interface{}{ - "test_key": "value1", - "test_tls_key": "value2", - "ttl": "value3", - "source_ip": "value4", - }, - "expected": map[string]interface{}{ - "TestKey": "value1", - "TestTLSKey": "value2", - "TTL": "value3", - "SourceIP": "value4", - }, - }, - { - "input": dummySetSchema, - "expected": map[string]interface{}{"TestSetKey": "test_value"}, - }, - } - for _, testCase := range dataSet { - res, err := formatKeys(testCase["input"], formatKey) - require.NoError(t, err) - require.Equal(t, testCase["expected"], res) - } -} From ee7e8705662d554cb852a2acc9203488dbd7eb9c Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 29 Sep 2023 09:33:30 +0530 Subject: [PATCH 47/89] fix upstream config --- ...ce_consul_config_entry_service_defaults.go | 2 +- ...l_config_entry_service_defaults_ce_test.go | 94 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 794ebbfd..c16589de 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -513,7 +513,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } upstreamConfigList := d.Get("upstream_config").(*schema.Set).List() - if len(upstreamConfigList) > 1 { + if len(upstreamConfigList) > 0 { configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} upstreamConfigMap := upstreamConfigList[0].(map[string]interface{}) defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go index 910479e2..07f323c3 100644 --- a/consul/resource_consul_config_entry_service_defaults_ce_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -64,47 +64,47 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { 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.1485775592.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.interval", "23900s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.base_ejection_time", "30309s"), 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"), @@ -218,11 +218,11 @@ resource "consul_config_entry_service_defaults" "bar" { max_concurrent_requests = 9399 } passive_health_check { - interval = 19 + interval = "19s" max_failures = 8 enforcing_consecutive_5xx = 10 max_ejection_percent = 10 - base_ejection_time = 30 + base_ejection_time = "30s" } } overrides { @@ -239,11 +239,11 @@ resource "consul_config_entry_service_defaults" "bar" { max_concurrent_requests = 9399 } passive_health_check { - interval = 19 + interval = "19s" max_failures = 8 enforcing_consecutive_5xx = 10 max_ejection_percent = 10 - base_ejection_time = 30 + base_ejection_time = "30s" } } defaults { @@ -259,11 +259,11 @@ resource "consul_config_entry_service_defaults" "bar" { max_concurrent_requests = 2900 } passive_health_check { - interval = 23900 + interval = "23900s" max_failures = 29030 enforcing_consecutive_5xx = 1 max_ejection_percent = 12 - base_ejection_time = 30309 + base_ejection_time = "30309s" } } } From bed043a1ec3e1ed754f380d9b6b1a7725e2289b6 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 29 Sep 2023 09:40:33 +0530 Subject: [PATCH 48/89] fix tests --- ...l_config_entry_service_defaults_ce_test.go | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go index 07f323c3..1ad9be3e 100644 --- a/consul/resource_consul_config_entry_service_defaults_ce_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -64,47 +64,47 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { 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.2229355929.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.interval", "19s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.interval", "19s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.protocol", "http"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.interval", "23900s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.2229355929.defaults.3577250670.passive_health_check.117760877.base_ejection_time", "30309s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.interval", "6h38m20s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.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"), @@ -259,11 +259,11 @@ resource "consul_config_entry_service_defaults" "bar" { max_concurrent_requests = 2900 } passive_health_check { - interval = "23900s" + interval = "6h38m20s" max_failures = 29030 enforcing_consecutive_5xx = 1 max_ejection_percent = 12 - base_ejection_time = "30309s" + base_ejection_time = "8h25m9s" } } } From 0e70cc21d49b1f77616c0da607c0264637b27ae5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 29 Sep 2023 12:14:55 +0530 Subject: [PATCH 49/89] Fix namespace --- consul/resource_consul_config_entry_service_defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index c16589de..677efd65 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -585,7 +585,7 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error sw.set("name", sd.Name) sw.set("partition", sd.Partition) - sw.set("namespace", sd.Partition) + sw.set("namespace", sd.Namespace) meta := make(map[string]interface{}) for k, v := range sd.Meta { From 405487b3271881571fe366f69319eaffb3cf2d98 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Fri, 29 Sep 2023 18:43:50 +0530 Subject: [PATCH 50/89] fix file name --- ...e_consul_config_entry_service_resolver.go} | 0 ...l_config_entry_service_resolver_ce_test.go | 82 +++++++++++++ ...l_config_entry_service_resolver_ee_test.go | 112 ++++++++++++++++++ 3 files changed, 194 insertions(+) rename consul/{resource_consul_service_resolver_config_entry.go => resource_consul_config_entry_service_resolver.go} (100%) create mode 100644 consul/resource_consul_config_entry_service_resolver_ce_test.go create mode 100644 consul/resource_consul_config_entry_service_resolver_ee_test.go diff --git a/consul/resource_consul_service_resolver_config_entry.go b/consul/resource_consul_config_entry_service_resolver.go similarity index 100% rename from consul/resource_consul_service_resolver_config_entry.go rename to consul/resource_consul_config_entry_service_resolver.go diff --git a/consul/resource_consul_config_entry_service_resolver_ce_test.go b/consul/resource_consul_config_entry_service_resolver_ce_test.go new file mode 100644 index 00000000..c985f9e7 --- /dev/null +++ b/consul/resource_consul_config_entry_service_resolver_ce_test.go @@ -0,0 +1,82 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceResolverCE, + Check: resource.ComposeTestCheckFunc(), + }, + }, + }) +} + +const testConsulConfigEntryServiceResolverCE = ` +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + +resource "consul_config_entry_service_splitter" "foo" { + name = consul_config_entry.service_resolver.name + meta = { + key = "value" + } + splits { + weight = 90 + service_subset = "v1" + service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } + } + splits { + weight = 10 + service = "web" + service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } + } +} +` diff --git a/consul/resource_consul_config_entry_service_resolver_ee_test.go b/consul/resource_consul_config_entry_service_resolver_ee_test.go new file mode 100644 index 00000000..f4856b25 --- /dev/null +++ b/consul/resource_consul_config_entry_service_resolver_ee_test.go @@ -0,0 +1,112 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceResolverEETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceResolverEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "namespace", "ns"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "partition", "pt"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), + ), + }, + }, + }) +} + +const testConsulConfigEntryServiceResolverEE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Protocol = "http" + Expose = {} + MeshGateway = {} + TransparentProxy = {} + }) +} + +resource "consul_config_entry" "service_resolver" { + kind = "service-resolver" + name = consul_config_entry.web.name + + config_json = jsonencode({ + DefaultSubset = "v1" + + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + } + "v2" = { + Filter = "Service.Meta.version == v2" + } + } + }) +} + +resource "consul_config_entry_service_splitter" "foo" { + name = consul_config_entry.service_resolver.name + namespace = "ns" + partition = "pt" + meta = { + key = "value" + } + splits { + weight = 90 + service_subset = "v1" + service = "web" + request_headers { + set = { + "x-web-version": "from-v1" + } + } + response_headers { + set = { + "x-web-version": "to-v1" + } + } + } + splits { + weight = 10 + service = "web" + service_subset = "v2" + request_headers { + set = { + "x-web-version": "from-v2" + } + } + response_headers { + set = { + "x-web-version": "to-v2" + } + } + } +} +` From 4d30f5a36883f5c160ca9fe46911a201300d610f Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 30 Sep 2023 16:16:10 +0530 Subject: [PATCH 51/89] manual test of service resolver --- ...ce_consul_config_entry_service_resolver.go | 73 +++++++++++++------ 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver.go b/consul/resource_consul_config_entry_service_resolver.go index 3c6a2446..cf7c9a6c 100644 --- a/consul/resource_consul_config_entry_service_resolver.go +++ b/consul/resource_consul_config_entry_service_resolver.go @@ -329,7 +329,7 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } configEntry.ConnectTimeout = connectTimeout - requestTimeout, err := time.ParseDuration(d.Get("connect_timeout").(string)) + requestTimeout, err := time.ParseDuration(d.Get("request_timeout").(string)) if err != nil { return nil, err } @@ -368,20 +368,43 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, for _, failoverElem := range failoverList { failoverMap := failoverElem.(map[string]interface{}) var serviceResolverFailover consulapi.ServiceResolverFailover - serviceResolverFailover.Service = failoverMap["service"].(string) - serviceResolverFailover.ServiceSubset = failoverMap["service_subset"].(string) - serviceResolverFailover.Namespace = failoverMap["namespace"].(string) - serviceResolverFailover.SamenessGroup = failoverMap["sameness_group"].(string) - serviceResolverFailover.Datacenters = failoverMap["datacenter"].([]string) + if value, ok := failoverMap["service"]; ok { + serviceResolverFailover.Service = value.(string) + } + if value, ok := failoverMap["service_subset"]; ok { + serviceResolverFailover.ServiceSubset = value.(string) + } + if value, ok := failoverMap["namespace"]; ok { + serviceResolverFailover.Namespace = value.(string) + } + if value, ok := failoverMap["sameness_group"]; ok { + serviceResolverFailover.SamenessGroup = value.(string) + } + if value, ok := failoverMap["datacenter"]; ok { + serviceResolverFailover.Datacenters = value.([]string) + } serviceResolverFailoverTargets := make([]consulapi.ServiceResolverFailoverTarget, len(failoverMap["targets"].([]interface{}))) - for indx, targetElem := range failoverMap["targets"].([]map[string]interface{}) { + for indx, target := range failoverMap["targets"].([]interface{}) { + targetElem := target.(map[string]interface{}) var serviceResolverFailoverTarget consulapi.ServiceResolverFailoverTarget - serviceResolverFailoverTarget.Service = targetElem["service"].(string) - serviceResolverFailoverTarget.ServiceSubset = targetElem["service_subset"].(string) - serviceResolverFailoverTarget.Namespace = targetElem["namespace"].(string) - serviceResolverFailoverTarget.Partition = targetElem["partition"].(string) - serviceResolverFailoverTarget.Datacenter = targetElem["datacenter"].(string) - serviceResolverFailoverTarget.Peer = targetElem["peer"].(string) + if value, ok := targetElem["service"]; ok { + serviceResolverFailoverTarget.Service = value.(string) + } + if value, ok := targetElem["service_subset"]; ok { + serviceResolverFailoverTarget.ServiceSubset = value.(string) + } + if value, ok := targetElem["namespace"]; ok { + serviceResolverFailoverTarget.Namespace = value.(string) + } + if value, ok := targetElem["partition"]; ok { + serviceResolverFailoverTarget.Partition = value.(string) + } + if value, ok := targetElem["datacenter"]; ok { + serviceResolverFailoverTarget.Datacenter = value.(string) + } + if value, ok := targetElem["peer"]; ok { + serviceResolverFailoverTarget.Peer = value.(string) + } serviceResolverFailoverTargets[indx] = serviceResolverFailoverTarget } serviceResolverFailover.Targets = serviceResolverFailoverTargets @@ -408,7 +431,7 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, ceLoadBalancer.RingHashConfig = rhConfig } if hp := loadBalancer["hash_policies"].([]interface{}); len(hp) > 0 { - var hashPolicyList []consulapi.HashPolicy + hashPolicyList := make([]consulapi.HashPolicy, len(hp)) for indx, hashPolicy := range hp { hashPolicyMap := hashPolicy.(map[string]interface{}) hashPolicyList[indx].Field = hashPolicyMap["field"].(string) @@ -452,8 +475,8 @@ func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error meta[k] = v } sw.set("meta", meta) - sw.set("connect_timeout", sr.ConnectTimeout) - sw.set("request_timeout", sr.RequestTimeout) + sw.set("connect_timeout", sr.ConnectTimeout.String()) + sw.set("request_timeout", sr.RequestTimeout.String()) subsets := make([]map[string]interface{}, len(sr.Subsets)) indx := 0 @@ -534,19 +557,21 @@ func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error if sr.LoadBalancer.HashPolicies != nil { hashPolicyList := make([]map[string]interface{}, len(sr.LoadBalancer.HashPolicies)) - for indx, hashPolicy := range sr.LoadBalancer.HashPolicies { + for index, hashPolicy := range sr.LoadBalancer.HashPolicies { hashPolicyMap := make(map[string]interface{}) hashPolicyMap["field"] = hashPolicy.Field hashPolicyMap["field_value"] = hashPolicy.FieldValue - cookieConfigSet := make([]map[string]interface{}, 1) - cookieConfigSet[0] = make(map[string]interface{}) - cookieConfigSet[0]["session"] = hashPolicy.CookieConfig.Session - cookieConfigSet[0]["ttl"] = hashPolicy.CookieConfig.TTL - cookieConfigSet[0]["path"] = hashPolicy.CookieConfig.TTL - hashPolicyMap["cookie_config"] = cookieConfigSet + if hashPolicy.CookieConfig != nil { + cookieConfigSet := make([]map[string]interface{}, 1) + cookieConfigSet[0] = make(map[string]interface{}) + cookieConfigSet[0]["session"] = hashPolicy.CookieConfig.Session + cookieConfigSet[0]["ttl"] = hashPolicy.CookieConfig.TTL + cookieConfigSet[0]["path"] = hashPolicy.CookieConfig.TTL + hashPolicyMap["cookie_config"] = cookieConfigSet + } hashPolicyMap["source_ip"] = hashPolicy.SourceIP hashPolicyMap["terminal"] = hashPolicy.Terminal - hashPolicyList[indx] = hashPolicyMap + hashPolicyList[index] = hashPolicyMap } loadBalancer[0]["hash_policies"] = hashPolicyList } From 83443fb381c4c00be580497b09ec7b9ed985b3e2 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 30 Sep 2023 17:23:11 +0530 Subject: [PATCH 52/89] server resolver tests flaky --- ...l_config_entry_service_resolver_ce_test.go | 179 +++++++++++++----- 1 file changed, 133 insertions(+), 46 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver_ce_test.go b/consul/resource_consul_config_entry_service_resolver_ce_test.go index c985f9e7..c6892be2 100644 --- a/consul/resource_consul_config_entry_service_resolver_ce_test.go +++ b/consul/resource_consul_config_entry_service_resolver_ce_test.go @@ -16,66 +16,153 @@ func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, Providers: providers, Steps: []resource.TestStep{ + //{ + // Config: testConsulConfigEntryServiceResolverCEWithRedirect, + // Check: resource.ComposeTestCheckFunc( + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "name", "consul-service-resolver-1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "meta.key", "value"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "connect_timeout", "10s"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "request_timeout", "10s"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.#", "2"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.name", "v1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.filter", "Service.Meta.version == v1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.only_passing", "true"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.name", "v2"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.filter", "Service.Meta.version == v2"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.only_passing", "true"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "default_subset", "v1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.#", "1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.1000671749.datacenter", "dc1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.policy", "ring_hash"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.#", "1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.#", "1"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field", "header"), + // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), + // ), + //}, { - Config: testConsulConfigEntryServiceResolverCE, - Check: resource.ComposeTestCheckFunc(), + Config: testConsulConfigEntryServiceResolverCEWithFailover, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "name", "consul-service-resolver-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "connect_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "request_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "default_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.subset_name", "*"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.service", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.datacenters", "[\"dc3\", \"dc4\"]"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.service", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.datacenters", "[\"dc2\"]"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.datacenter", "dc1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.datacenters", "[\"dc2\"]"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.policy", "ring_hash"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.0.field", "header"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), + ), }, }, }) } -const testConsulConfigEntryServiceResolverCE = ` -resource "consul_config_entry" "service_resolver" { - kind = "service-resolver" - name = consul_config_entry.web.name - - config_json = jsonencode({ - DefaultSubset = "v1" - - Subsets = { - "v1" = { - Filter = "Service.Meta.version == v1" - } - "v2" = { - Filter = "Service.Meta.version == v2" - } +const testConsulConfigEntryServiceResolverCEWithRedirect = ` +resource "consul_config_entry_service_resolver" "foo" { + name = "consul-service-resolver-1" + meta = { + key: "value" + } + connect_timeout = "10s" + request_timeout = "10s" + subsets { + name = "v1" + filter = "Service.Meta.version == v1" + only_passing = true + } + subsets { + name = "v2" + filter = "Service.Meta.version == v2" + only_passing = true + } + default_subset = "v1" + redirect { + datacenter = "dc1" + } + load_balancer { + policy = "ring_hash" + ring_hash_config { + minimum_ring_size = 3 + maximum_ring_size = 10 } - }) + hash_policies { + field = "header" + field_value = "x-user-id" + } + } } +` -resource "consul_config_entry_service_splitter" "foo" { - name = consul_config_entry.service_resolver.name +const testConsulConfigEntryServiceResolverCEWithFailover = ` +resource "consul_config_entry_service_resolver" "bar" { + name = "consul-service-resolver-2" meta = { - key = "value" + key: "value" } - splits { - weight = 90 - service_subset = "v1" - service = "web" - request_headers { - set = { - "x-web-version": "from-v1" - } - } - response_headers { - set = { - "x-web-version": "to-v1" - } + connect_timeout = "10s" + request_timeout = "10s" + subsets { + name = "v1" + filter = "Service.Meta.version == v1" + only_passing = true + } + subsets { + name = "v2" + filter = "Service.Meta.version == v2" + only_passing = true + } + default_subset = "v1" + failover { + subset_name = "*" + service = "backend" + datacenters = ["dc3", "dc4"] + } + failover { + subset_name = "v2" + service = "frontend" + datacenters = ["dc2"] + } + failover { + subset_name = "v1" + targets { + service_subset = "v1" + datacenter = "dc1" } } - splits { - weight = 10 - service = "web" - service_subset = "v2" - request_headers { - set = { - "x-web-version": "from-v2" - } + load_balancer { + policy = "ring_hash" + ring_hash_config { + minimum_ring_size = 3 + maximum_ring_size = 10 } - response_headers { - set = { - "x-web-version": "to-v2" - } + hash_policies { + field = "header" + field_value = "x-user-id" } } } From e35b1308ce1a0e7caadfcc629684111b6969ca02 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 30 Sep 2023 17:23:35 +0530 Subject: [PATCH 53/89] resolver tests --- ...l_config_entry_service_resolver_ce_test.go | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver_ce_test.go b/consul/resource_consul_config_entry_service_resolver_ce_test.go index c6892be2..957bfe5a 100644 --- a/consul/resource_consul_config_entry_service_resolver_ce_test.go +++ b/consul/resource_consul_config_entry_service_resolver_ce_test.go @@ -16,32 +16,32 @@ func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, Providers: providers, Steps: []resource.TestStep{ - //{ - // Config: testConsulConfigEntryServiceResolverCEWithRedirect, - // Check: resource.ComposeTestCheckFunc( - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "name", "consul-service-resolver-1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "meta.key", "value"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "connect_timeout", "10s"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "request_timeout", "10s"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.#", "2"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.name", "v1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.filter", "Service.Meta.version == v1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.only_passing", "true"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.name", "v2"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.filter", "Service.Meta.version == v2"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.only_passing", "true"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "default_subset", "v1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.#", "1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.1000671749.datacenter", "dc1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.policy", "ring_hash"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.#", "1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.#", "1"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field", "header"), - // resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), - // ), - //}, + { + Config: testConsulConfigEntryServiceResolverCEWithRedirect, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "name", "consul-service-resolver-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "connect_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "request_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "default_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.1000671749.datacenter", "dc1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.policy", "ring_hash"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field", "header"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), + ), + }, { Config: testConsulConfigEntryServiceResolverCEWithFailover, Check: resource.ComposeTestCheckFunc( From 3bbe42c83c6095a7b8762c62efbb58cbe76b79e5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 30 Sep 2023 17:32:18 +0530 Subject: [PATCH 54/89] tests commented --- ...l_config_entry_service_resolver_ce_test.go | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver_ce_test.go b/consul/resource_consul_config_entry_service_resolver_ce_test.go index 957bfe5a..61b462f2 100644 --- a/consul/resource_consul_config_entry_service_resolver_ce_test.go +++ b/consul/resource_consul_config_entry_service_resolver_ce_test.go @@ -57,18 +57,18 @@ func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.filter", "Service.Meta.version == v2"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.only_passing", "true"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "default_subset", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.subset_name", "*"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.service", "backend"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.datacenters", "[\"dc3\", \"dc4\"]"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.service", "frontend"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.datacenters", "[\"dc2\"]"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.datacenter", "dc1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.datacenters", "[\"dc2\"]"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.subset_name", "*"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.service", "backend"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.datacenters", "[\"dc3\", \"dc4\"]"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v2"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.service", "frontend"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.datacenters", "[\"dc2\"]"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.#", "1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.service_subset", "v1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.datacenter", "dc1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.datacenters", "[\"dc2\"]"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.policy", "ring_hash"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.#", "1"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), From 93ba3d6db334b6cadaee0a153b348c321cde265a Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sat, 30 Sep 2023 17:33:36 +0530 Subject: [PATCH 55/89] ee tests --- ...l_config_entry_service_resolver_ee_test.go | 205 +++++++++++------- 1 file changed, 131 insertions(+), 74 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver_ee_test.go b/consul/resource_consul_config_entry_service_resolver_ee_test.go index f4856b25..47a76e30 100644 --- a/consul/resource_consul_config_entry_service_resolver_ee_test.go +++ b/consul/resource_consul_config_entry_service_resolver_ee_test.go @@ -17,95 +17,152 @@ func TestAccConsulConfigEntryServiceResolverEETest(t *testing.T) { Providers: providers, Steps: []resource.TestStep{ { - Config: testConsulConfigEntryServiceResolverEE, + Config: testConsulConfigEntryServiceResolverEEWithRedirect, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "name", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "namespace", "ns"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "partition", "pt"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "meta.key", "value"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.#", "2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.weight", "90"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.service_subset", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.request_headers.0.set.x-web-version", "from-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.0.response_headers.0.set.x-web-version", "to-v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.weight", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service_subset", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.service", "web"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.request_headers.0.set.x-web-version", "from-v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_splitter.foo", "splits.1.response_headers.0.set.x-web-version", "to-v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "name", "consul-service-resolver-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "connect_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "request_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "default_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.1000671749.datacenter", "dc1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.policy", "ring_hash"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field", "header"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), + ), + }, + { + Config: testConsulConfigEntryServiceResolverEEWithFailover, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "name", "consul-service-resolver-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "connect_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "request_timeout", "10s"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.#", "2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "default_subset", "v1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.subset_name", "*"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.service", "backend"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.datacenters", "[\"dc3\", \"dc4\"]"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v2"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.service", "frontend"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.datacenters", "[\"dc2\"]"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.#", "1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.service_subset", "v1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.datacenter", "dc1"), + //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.datacenters", "[\"dc2\"]"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.policy", "ring_hash"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.maximum_ring_size", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.0.field", "header"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.hash_policies.0.field_value", "x-user-id"), ), }, }, }) } -const testConsulConfigEntryServiceResolverEE = ` -resource "consul_config_entry" "web" { - name = "web" - kind = "service-defaults" - - config_json = jsonencode({ - Protocol = "http" - Expose = {} - MeshGateway = {} - TransparentProxy = {} - }) -} - -resource "consul_config_entry" "service_resolver" { - kind = "service-resolver" - name = consul_config_entry.web.name - - config_json = jsonencode({ - DefaultSubset = "v1" - - Subsets = { - "v1" = { - Filter = "Service.Meta.version == v1" - } - "v2" = { - Filter = "Service.Meta.version == v2" - } +const testConsulConfigEntryServiceResolverEEWithRedirect = ` +resource "consul_config_entry_service_resolver" "foo" { + name = "consul-service-resolver-1" + meta = { + key: "value" + } + connect_timeout = "10s" + request_timeout = "10s" + subsets { + name = "v1" + filter = "Service.Meta.version == v1" + only_passing = true + } + subsets { + name = "v2" + filter = "Service.Meta.version == v2" + only_passing = true + } + default_subset = "v1" + redirect { + datacenter = "dc1" + } + load_balancer { + policy = "ring_hash" + ring_hash_config { + minimum_ring_size = 3 + maximum_ring_size = 10 } - }) + hash_policies { + field = "header" + field_value = "x-user-id" + } + } } +` -resource "consul_config_entry_service_splitter" "foo" { - name = consul_config_entry.service_resolver.name - namespace = "ns" - partition = "pt" +const testConsulConfigEntryServiceResolverEEWithFailover = ` +resource "consul_config_entry_service_resolver" "bar" { + name = "consul-service-resolver-2" meta = { - key = "value" + key: "value" } - splits { - weight = 90 - service_subset = "v1" - service = "web" - request_headers { - set = { - "x-web-version": "from-v1" - } - } - response_headers { - set = { - "x-web-version": "to-v1" - } + connect_timeout = "10s" + request_timeout = "10s" + subsets { + name = "v1" + filter = "Service.Meta.version == v1" + only_passing = true + } + subsets { + name = "v2" + filter = "Service.Meta.version == v2" + only_passing = true + } + default_subset = "v1" + failover { + subset_name = "*" + service = "backend" + datacenters = ["dc3", "dc4"] + } + failover { + subset_name = "v2" + service = "frontend" + datacenters = ["dc2"] + } + failover { + subset_name = "v1" + targets { + service_subset = "v1" + datacenter = "dc1" } } - splits { - weight = 10 - service = "web" - service_subset = "v2" - request_headers { - set = { - "x-web-version": "from-v2" - } + load_balancer { + policy = "ring_hash" + ring_hash_config { + minimum_ring_size = 3 + maximum_ring_size = 10 } - response_headers { - set = { - "x-web-version": "to-v2" - } + hash_policies { + field = "header" + field_value = "x-user-id" } } } From c843ac8dcacfd7a2d608ed947c3fbd563d66cab5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Sun, 1 Oct 2023 19:26:44 +0530 Subject: [PATCH 56/89] init --- ...urce_consul_config_entry_service_router.go | 285 ++++++++++++++++++ consul/resource_provider.go | 1 + 2 files changed, 286 insertions(+) create mode 100644 consul/resource_consul_config_entry_service_router.go diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go new file mode 100644 index 00000000..77ec4e93 --- /dev/null +++ b/consul/resource_consul_config_entry_service_router.go @@ -0,0 +1,285 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "golang.org/x/net/route" +) + +type serviceRouter struct{} + +func (s *serviceRouter) GetKind() string { + return consulapi.ServiceRouter +} + +func (s *serviceRouter) GetDescription() string { + return "The `consul_config_entry_service_router` resource configures a [service router](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router) to redirect a traffic request for a service to one or more specific service instances.", +} + +func (s *serviceRouter) GetSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "Specifies a name for the configuration entry.", + Required: true, + ForceNew: true, + }, + "partition": { + Type: schema.TypeString, + Description: "Specifies the admin partition to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "namespace": { + Type: schema.TypeString, + Description: "Specifies the namespace to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "meta": { + Type: schema.TypeMap, + Description: "Specifies key-value pairs to add to the KV store.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "routes": { + Type: schema.TypeList, + Description: "", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "match": { + Type: schema.TypeSet, + Description: "", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http": { + Type: schema.TypeSet, + Description: "", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path_exact": { + Type: schema.TypeString, + Description: "", + }, + "path_prefix": { + Type: schema.TypeString, + Description: "", + }, + "path_regex": { + Type: schema.TypeString, + Description: "", + }, + "methods": { + Type: schema.TypeList, + Elem: schema.TypeString, + }, + "header": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + }, + "present": { + Type: schema.TypeBool, + }, + "exact": { + Type: schema.TypeString, + }, + "prefix": { + Type: schema.TypeString, + }, + "suffix": { + Type: schema.TypeString, + }, + "regex": { + Type: schema.TypeString, + }, + "invert": { + Type: schema.TypeBool, + }, + }, + }, + }, + "query_param": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + }, + "present": { + Type: schema.TypeBool, + }, + "exact": { + Type: schema.TypeString, + }, + "regex": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "destination": { + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + }, + "service_subset": { + Type: schema.TypeString, + }, + "namespace": { + Type: schema.TypeString, + }, + "partition": { + Type: schema.TypeString, + }, + "prefix_rewrite": { + Type: schema.TypeString, + }, + "request_timeout": { + Type: schema.TypeInt, + }, + "idle_timeout": { + Type: schema.TypeInt, + }, + "num_retries": { + Type: schema.TypeInt, + }, + "retry_on_connect_failure": { + Type: schema.TypeBool, + }, + "retry_on": { + Type: schema.TypeList, + Elem: schema.TypeString, + }, + "retry_on_status_code": { + Type: schema.TypeList, + Elem: schema.TypeInt, + }, + "request_headers": { + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + "set": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + "remote": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + }, + }, + }, + "response_headers": { + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + "set": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + "remote": { + Type: schema.TypeMap, + Elem: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { + configEntry := &consulapi.ServiceRouterConfigEntry{ + Kind: consulapi.ServiceRouter, + Name: d.Get("name").(string), + Partition: d.Get("partition").(string), + Namespace: d.Get("namespace").(string), + Meta: map[string]string{}, + } + + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) + } + + routes := d.Get("routes") + if routes != nil { + routeList := routes.([]interface{}) + serviceRoutesList := make([]consulapi.ServiceRoute, len(routeList)) + for indx, r := range routeList { + routListMap := r.(map[string]interface{}) + matchMap := routListMap["match"].(map[string]interface{}) + matchHTTP := matchMap["HTTP"].(map[string]interface{}) + var matchRoute *consulapi.ServiceRouteMatch + matchRoute = new(consulapi.ServiceRouteMatch) + var serviceRouteHTTPMatch *consulapi.ServiceRouteHTTPMatch + serviceRouteHTTPMatch = new(consulapi.ServiceRouteHTTPMatch) + serviceRouteHTTPMatch.PathExact = matchHTTP["path_exact"].(string) + serviceRouteHTTPMatch.PathPrefix = matchHTTP["path_prefix"].(string) + serviceRouteHTTPMatch.PathRegex = matchHTTP["path_regex"].(string) + serviceRouteHTTPMatch.Methods = matchHTTP["methods"].([]string) + var headers []consulapi.ServiceRouteHTTPMatchHeader + matchHeaders := matchHTTP["header"].([]interface{}) + for index, h := range matchHeaders { + header := h.(map[string]interface{}) + matchHeader := &consulapi.ServiceRouteHTTPMatchHeader{ + Name: header["name"].(string), + Present: header["present"].(bool), + Exact: header["exact"].(string), + Prefix: header["prefix"].(string), + Suffix: header["suffix"].(string), + Regex: header["regex"].(string), + Invert: header["present"].(bool), + } + headers[index] = *matchHeader + } + serviceRouteHTTPMatch.Header = headers + queryParam := matchHTTP["query_param"].([]interface{}) + queryParamList := make([]consulapi.ServiceRouteHTTPMatchQueryParam, len(queryParam)) + for index, q := range queryParam { + queryParamMap := q.(map[string]interface{}) + queryParamList[index].Name = queryParamMap["name"].(string) + queryParamList[index].Regex = queryParamMap["regex"].(string) + queryParamList[index].Present = queryParamMap["present"].(bool) + queryParamList[index].Exact = queryParamMap["exact"].(string) + } + serviceRouteHTTPMatch.QueryParam = queryParamList + matchRoute.HTTP = serviceRouteHTTPMatch + serviceRoutesList[indx].Match = matchRoute + //serviceRoutesList[indx].Destination = destination + } + configEntry.Routes = serviceRoutesList + } + +} + +func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { + +} diff --git a/consul/resource_provider.go b/consul/resource_provider.go index c32e164b..aa40dee9 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -239,6 +239,7 @@ func Provider() terraform.ResourceProvider { "consul_certificate_authority": resourceConsulCertificateAuthority(), "consul_config_entry_service_splitter": resourceFromConfigEntryImplementation(&serviceSplitter{}), "consul_config_entry_service_defaults": resourceFromConfigEntryImplementation(&serviceDefaults{}), + "consul_config_entry_service_router": resourceFromConfigEntryImplementation(&serviceRouter{}), "consul_config_entry": resourceConsulConfigEntry(), "consul_intention": resourceConsulIntention(), "consul_key_prefix": resourceConsulKeyPrefix(), From 9730ae1b9bb757b5c9c6b56b379ffb3eb9d53192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Mon, 2 Oct 2023 00:54:32 +0200 Subject: [PATCH 57/89] Simplify serviceDefaults.Decode() --- .../data_source_consul_service_health_test.go | 3 +- consul/data_source_consul_service_test.go | 3 +- ...ce_consul_config_entry_service_defaults.go | 196 +++++++--------- consul/resource_provider_test.go | 2 + .../config_entry_service_defaults.md | 208 +++++++++++++++++ .../service_defaults_config_entry.md | 209 ------------------ 6 files changed, 297 insertions(+), 324 deletions(-) create mode 100644 docs/resources/config_entry_service_defaults.md delete mode 100644 docs/resources/service_defaults_config_entry.md diff --git a/consul/data_source_consul_service_health_test.go b/consul/data_source_consul_service_health_test.go index 45a9eb16..2e8c528d 100644 --- a/consul/data_source_consul_service_health_test.go +++ b/consul/data_source_consul_service_health_test.go @@ -33,8 +33,9 @@ func TestAccDataConsulServiceHealth(t *testing.T) { testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.address", ""), testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.datacenter", "dc1"), testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.tagged_addresses.%", "4"), - testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.meta.%", "1"), + testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.meta.%", "2"), testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.meta.consul-network-segment", ""), + testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.meta.consul-version", ""), testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.service.0.id", "consul"), testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.service.0.name", "consul"), diff --git a/consul/data_source_consul_service_test.go b/consul/data_source_consul_service_test.go index 78a40f40..bc36d6cc 100644 --- a/consul/data_source_consul_service_test.go +++ b/consul/data_source_consul_service_test.go @@ -28,8 +28,9 @@ func TestAccDataConsulService_basic(t *testing.T) { testAccCheckDataSourceValue("data.consul_service.read", "service.0.name", ""), testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_address", ""), testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_id", ""), - testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_meta.%", "1"), + testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_meta.%", "2"), testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_meta.consul-network-segment", ""), + testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_meta.consul-version", ""), testAccCheckDataSourceValue("data.consul_service.read", "service.0.node_name", ""), testAccCheckDataSourceValue("data.consul_service.read", "service.0.port", ""), testAccCheckDataSourceValue("data.consul_service.read", "service.0.tagged_addresses.%", "4"), diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 677efd65..710f75f3 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -5,9 +5,10 @@ package consul import ( "fmt" + "time" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "time" ) type serviceDefaults struct{} @@ -138,54 +139,47 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, } - return map[string]*schema.Schema{ + 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, @@ -207,7 +201,6 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, }, - "transparent_proxy": { Type: schema.TypeSet, Optional: true, @@ -225,13 +218,11 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, }, - "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, @@ -262,7 +253,6 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, }, - "destination": { Type: schema.TypeSet, Optional: true, @@ -281,25 +271,21 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, }, - "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, @@ -313,13 +299,11 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, }, - "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, @@ -364,63 +348,63 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { 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), - Namespace: d.Get("namespace").(string), - Meta: map[string]string{}, + Kind: consulapi.ServiceDefaults, + Name: d.Get("name").(string), + Partition: d.Get("partition").(string), + Namespace: d.Get("namespace").(string), + Protocol: d.Get("protocol").(string), + BalanceInboundConnections: d.Get("balance_inbound_connections").(string), + LocalConnectTimeoutMs: d.Get("local_connect_timeout_ms").(int), + MaxInboundConnections: d.Get("max_inbound_connections").(int), + LocalRequestTimeoutMs: d.Get("local_request_timeout_ms").(int), + ExternalSNI: d.Get("external_sni").(string), + Mode: consulapi.ProxyMode(d.Get("mode").(string)), + MutualTLSMode: consulapi.MutualTLSMode(d.Get("mutual_tls_mode").(string)), + Meta: map[string]string{}, } for k, v := range d.Get("meta").(map[string]interface{}) { configEntry.Meta[k] = v.(string) } - configEntry.Protocol = d.Get("protocol").(string) - configEntry.BalanceInboundConnections = d.Get("balance_inbound_connections").(string) - - proxyMode := consulapi.ProxyMode(d.Get("mode").(string)) - configEntry.Mode = proxyMode - getLimits := func(limitsMap map[string]interface{}) *consulapi.UpstreamLimits { - upstreamLimit := &consulapi.UpstreamLimits{} - var maxPendingRequests *int - maxPendingRequests = new(int) - *maxPendingRequests = limitsMap["max_pending_requests"].(int) - upstreamLimit.MaxPendingRequests = maxPendingRequests - var maxConnections *int - maxConnections = new(int) - *maxConnections = limitsMap["max_connections"].(int) - upstreamLimit.MaxConnections = maxConnections - var maxConcurrentRequests *int - maxConcurrentRequests = new(int) - *maxConcurrentRequests = limitsMap["max_concurrent_requests"].(int) - upstreamLimit.MaxConcurrentRequests = maxConcurrentRequests - return upstreamLimit + 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{}) - passiveHealthCheck := &consulapi.PassiveHealthCheck{} + 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, err + return nil, fmt.Errorf("failed to parse interval: %w", err) } passiveHealthCheck.Interval = duration - passiveHealthCheck.MaxFailures = uint32(passiveHealthCheckMap["max_failures"].(int)) - var enforcingConsecutive5xx *uint32 - enforcingConsecutive5xx = new(uint32) - *enforcingConsecutive5xx = uint32(passiveHealthCheckMap["enforcing_consecutive_5xx"].(int)) - passiveHealthCheck.EnforcingConsecutive5xx = enforcingConsecutive5xx - var maxEjectionPercentage *uint32 - maxEjectionPercentage = new(uint32) - *maxEjectionPercentage = uint32(passiveHealthCheckMap["max_ejection_percent"].(int)) - passiveHealthCheck.EnforcingConsecutive5xx = enforcingConsecutive5xx - passiveHealthCheck.MaxEjectionPercent = maxEjectionPercentage baseEjectionTime, err := time.ParseDuration(passiveHealthCheckMap["base_ejection_time"].(string)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to parse base_ejection_time: %w", err) } passiveHealthCheck.BaseEjectionTime = &baseEjectionTime return passiveHealthCheck, nil @@ -432,25 +416,25 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, meshGatewayList := meshGateway.(*schema.Set).List() if len(meshGatewayList) > 0 { meshGatewayData := meshGatewayList[0].(map[string]interface{}) - meshGatewayMode := consulapi.MeshGatewayMode(meshGatewayData["mode"].(string)) - meshGateway := &consulapi.MeshGatewayConfig{} - meshGateway.Mode = meshGatewayMode - return meshGateway + return &consulapi.MeshGatewayConfig{ + Mode: consulapi.MeshGatewayMode(meshGatewayData["mode"].(string)), + } } return nil } getUpstreamConfig := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { - upstreamConfig := &consulapi.UpstreamConfig{} - upstreamConfig.Name = upstreamConfigMap["name"].(string) - upstreamConfig.Partition = upstreamConfigMap["partition"].(string) - upstreamConfig.Namespace = upstreamConfigMap["namespace"].(string) - upstreamConfig.Peer = upstreamConfigMap["peer"].(string) - upstreamConfig.EnvoyListenerJSON = upstreamConfigMap["envoy_listener_json"].(string) - upstreamConfig.EnvoyClusterJSON = upstreamConfigMap["envoy_cluster_json"].(string) - upstreamConfig.Protocol = upstreamConfigMap["protocol"].(string) - upstreamConfig.ConnectTimeoutMs = upstreamConfigMap["connect_timeout_ms"].(int) - upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})) + upstreamConfig := &consulapi.UpstreamConfig{ + Name: upstreamConfigMap["name"].(string), + Partition: upstreamConfigMap["partition"].(string), + Namespace: upstreamConfigMap["namespace"].(string), + Peer: upstreamConfigMap["peer"].(string), + EnvoyListenerJSON: upstreamConfigMap["envoy_listener_json"].(string), + EnvoyClusterJSON: upstreamConfigMap["envoy_cluster_json"].(string), + Protocol: upstreamConfigMap["protocol"].(string), + ConnectTimeoutMs: upstreamConfigMap["connect_timeout_ms"].(int), + Limits: getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})), + } passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) if err != nil { return nil, err @@ -462,53 +446,51 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } getTransparentProxy := func(transparentProxy map[string]interface{}) *consulapi.TransparentProxyConfig { - tProxy := &consulapi.TransparentProxyConfig{} - tProxy.OutboundListenerPort = transparentProxy["outbound_listener_port"].(int) - tProxy.DialedDirectly = transparentProxy["dialed_directly"].(bool) - return tProxy + return &consulapi.TransparentProxyConfig{ + OutboundListenerPort: transparentProxy["outbound_listener_port"].(int), + DialedDirectly: transparentProxy["dialed_directly"].(bool), + } } getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) *consulapi.EnvoyExtension { - envoyExtension := &consulapi.EnvoyExtension{} - envoyExtension.Name = envoyExtensionMap["name"].(string) - envoyExtension.Required = envoyExtensionMap["required"].(bool) - envoyExtension.Arguments = envoyExtensionMap["arguments"].(map[string]interface{}) - envoyExtension.ConsulVersion = envoyExtensionMap["consul_version"].(string) - envoyExtension.EnvoyVersion = envoyExtensionMap["envoy_version"].(string) - return envoyExtension + return &consulapi.EnvoyExtension{ + Name: envoyExtensionMap["name"].(string), + Required: envoyExtensionMap["required"].(bool), + Arguments: envoyExtensionMap["arguments"].(map[string]interface{}), + ConsulVersion: envoyExtensionMap["consul_version"].(string), + EnvoyVersion: envoyExtensionMap["envoy_version"].(string), + } } getDestination := func(destinationMap map[string]interface{}) *consulapi.DestinationConfig { if destinationMap != nil { - var destination consulapi.DestinationConfig - destination.Port = destinationMap["port"].(int) - addresess := make([]string, len(destinationMap["addresses"].([]interface{}))) - for indx, address := range destinationMap["addresses"].([]interface{}) { - addresess[indx] = address.(string) + destination := &consulapi.DestinationConfig{ + Port: destinationMap["port"].(int), } - destination.Addresses = addresess - return &destination + 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{} - exposePath.Path = exposePathMap["path"].(string) - exposePath.LocalPathPort = exposePathMap["local_path_port"].(int) - exposePath.ListenerPort = exposePathMap["listener_port"].(int) - exposePath.Protocol = exposePathMap["protocol"].(string) - return exposePath + return &consulapi.ExposePath{ + Path: exposePathMap["path"].(string), + LocalPathPort: exposePathMap["local_path_port"].(int), + ListenerPort: exposePathMap["listener_port"].(int), + Protocol: exposePathMap["protocol"].(string), + } } getExpose := func(exposeMap map[string]interface{}) consulapi.ExposeConfig { - var exposeConfig consulapi.ExposeConfig - exposeConfig.Checks = exposeMap["checks"].(bool) - var paths []consulapi.ExposePath + exposeConfig := consulapi.ExposeConfig{ + Checks: exposeMap["checks"].(bool), + } for _, elem := range exposeMap["paths"].([]interface{}) { - paths = append(paths, *getExposePath(elem.(map[string]interface{}))) + exposeConfig.Paths = append(exposeConfig.Paths, *getExposePath(elem.(map[string]interface{}))) } - exposeConfig.Paths = paths return exposeConfig } @@ -543,32 +525,20 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, configEntry.TransparentProxy = getTransparentProxy(transparentProxy) } - mutualTLSmode := consulapi.MutualTLSMode(d.Get("mutual_tls_mode").(string)) - configEntry.MutualTLSMode = mutualTLSmode - - var envoyExtensions []consulapi.EnvoyExtension - for _, elem := range d.Get("envoy_extensions").([]interface{}) { envoyExtensionMap := elem.(map[string]interface{}) - envoyExtensions = append(envoyExtensions, *getEnvoyExtension(envoyExtensionMap)) + configEntry.EnvoyExtensions = append(configEntry.EnvoyExtensions, *getEnvoyExtension(envoyExtensionMap)) } - configEntry.EnvoyExtensions = envoyExtensions destinationList := d.Get("destination").(*schema.Set).List() if len(destinationList) > 0 { configEntry.Destination = getDestination(destinationList[0].(map[string]interface{})) } - configEntry.LocalConnectTimeoutMs = d.Get("local_connect_timeout_ms").(int) - configEntry.MaxInboundConnections = d.Get("max_inbound_connections").(int) - configEntry.LocalRequestTimeoutMs = d.Get("local_request_timeout_ms").(int) - if v := getMeshGateway(d.Get("mesh_gateway")); v != nil { configEntry.MeshGateway = *v } - configEntry.ExternalSNI = d.Get("external_sni").(string) - exposeList := d.Get("expose").(*schema.Set).List() if len(exposeList) > 0 { configEntry.Expose = getExpose(exposeList[0].(map[string]interface{})) diff --git a/consul/resource_provider_test.go b/consul/resource_provider_test.go index dde1a8b1..7c074db8 100644 --- a/consul/resource_provider_test.go +++ b/consul/resource_provider_test.go @@ -364,6 +364,8 @@ func waitForService(t *testing.T, address string) (terraform.ResourceProvider, * logger("got wrong number of services: %d", len(services)) } else if len(services[0].Node.Meta) == 0 { logger("got empty metadata") + } else if len(services[0].Node.Meta) < 2 { + logger("missing metadata") } else { return Provider(), client } diff --git a/docs/resources/config_entry_service_defaults.md b/docs/resources/config_entry_service_defaults.md new file mode 100644 index 00000000..4265f0bd --- /dev/null +++ b/docs/resources/config_entry_service_defaults.md @@ -0,0 +1,208 @@ +--- +# 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 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) 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) +- `envoy_cluster_json` (String) +- `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--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)) +- `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--defaults--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.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_cluster_json` (String) +- `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. + + diff --git a/docs/resources/service_defaults_config_entry.md b/docs/resources/service_defaults_config_entry.md deleted file mode 100644 index d3780e6a..00000000 --- a/docs/resources/service_defaults_config_entry.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "consul_service_defaults_config_entry Resource - terraform-provider-consul" -subcategory: "" -description: |- - ---- - -# consul_service_defaults_config_entry (Resource) - - - - - - -## Schema - -### Required - -- `expose` (Block Set, Min: 1) (see [below for nested schema](#nestedblock--expose)) -- `name` (String) -- `protocol` (String) - -### Optional - -- `balance_inbound_connections` (String) -- `destination` (Block Set) (see [below for nested schema](#nestedblock--destination)) -- `envoy_extensions` (Block List) (see [below for nested schema](#nestedblock--envoy_extensions)) -- `external_sni` (String) -- `local_connect_timeout_ms` (Number) -- `local_request_timeout_ms` (Number) -- `max_inbound_connections` (Number) -- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--mesh_gateway)) -- `meta` (Map of String) -- `mode` (String) -- `mutual_tls_mode` (String) -- `namespace` (String) -- `partition` (String) The partition the config entry is associated with. -- `transparent_proxy` (Block Set) (see [below for nested schema](#nestedblock--transparent_proxy)) -- `upstream_config` (Block Set) (see [below for nested schema](#nestedblock--upstream_config)) - -### Read-Only - -- `id` (String) The ID of this resource. -- `kind` (String) - - -### 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) (see [below for nested schema](#nestedblock--upstream_config--defaults)) -- `overrides` (Block List) (see [below for nested schema](#nestedblock--upstream_config--overrides)) - - -### Nested Schema for `upstream_config.defaults` - -Optional: - -- `balance_outbound_connections` (String) -- `connect_timeout_ms` (String) -- `envoy_cluster_json` (String) -- `envoy_listener_json` (String) -- `limits` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--limits)) -- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--mesh_gateway)) -- `name` (String) -- `namespace` (String) -- `partition` (String) -- `passive_health_check` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--defaults--passive_health_check)) -- `peer` (String) -- `protocol` (String) - - -### Nested Schema for `upstream_config.defaults.limits` - -Optional: - -- `max_concurrent_requests` (Number) -- `max_connections` (Number) -- `max_pending_requests` (Number) - - - -### Nested Schema for `upstream_config.defaults.mesh_gateway` - -Optional: - -- `mode` (String) - - - -### Nested Schema for `upstream_config.defaults.passive_health_check` - -Optional: - -- `base_ejection_time` (Number) -- `enforcing_consecutive_5xx` (Number) -- `interval` (Number) -- `max_ejection_percent` (Number) -- `max_failures` (Number) - - - - -### Nested Schema for `upstream_config.overrides` - -Optional: - -- `balance_outbound_connections` (String) -- `connect_timeout_ms` (String) -- `envoy_cluster_json` (String) -- `envoy_listener_json` (String) -- `limits` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--limits)) -- `mesh_gateway` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--mesh_gateway)) -- `name` (String) -- `namespace` (String) -- `partition` (String) -- `passive_health_check` (Block Set) (see [below for nested schema](#nestedblock--upstream_config--overrides--passive_health_check)) -- `peer` (String) -- `protocol` (String) - - -### Nested Schema for `upstream_config.overrides.limits` - -Optional: - -- `max_concurrent_requests` (Number) -- `max_connections` (Number) -- `max_pending_requests` (Number) - - - -### Nested Schema for `upstream_config.overrides.mesh_gateway` - -Optional: - -- `mode` (String) - - - -### Nested Schema for `upstream_config.overrides.passive_health_check` - -Optional: - -- `base_ejection_time` (Number) -- `enforcing_consecutive_5xx` (Number) -- `interval` (Number) -- `max_ejection_percent` (Number) -- `max_failures` (Number) - - From 94d240fca3d490faf7279f3523b0f6b8e08c9761 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 2 Oct 2023 09:03:24 +0530 Subject: [PATCH 58/89] fix errors --- ...urce_consul_config_entry_service_router.go | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 77ec4e93..e141f2ae 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -4,10 +4,8 @@ package consul import ( - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "golang.org/x/net/route" ) type serviceRouter struct{} @@ -17,7 +15,7 @@ func (s *serviceRouter) GetKind() string { } func (s *serviceRouter) GetDescription() string { - return "The `consul_config_entry_service_router` resource configures a [service router](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router) to redirect a traffic request for a service to one or more specific service instances.", + return "The `consul_config_entry_service_router` resource configures a [service router](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router) to redirect a traffic request for a service to one or more specific service instances." } func (s *serviceRouter) GetSchema() map[string]*schema.Schema { @@ -47,30 +45,30 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Elem: &schema.Schema{Type: schema.TypeString}, }, "routes": { - Type: schema.TypeList, + Type: schema.TypeList, Description: "", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "match": { - Type: schema.TypeSet, + Type: schema.TypeSet, Description: "", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "http": { - Type: schema.TypeSet, + Type: schema.TypeSet, Description: "", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "path_exact": { - Type: schema.TypeString, + Type: schema.TypeString, Description: "", }, "path_prefix": { - Type: schema.TypeString, + Type: schema.TypeString, Description: "", }, "path_regex": { - Type: schema.TypeString, + Type: schema.TypeString, Description: "", }, "methods": { @@ -250,13 +248,13 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e for index, h := range matchHeaders { header := h.(map[string]interface{}) matchHeader := &consulapi.ServiceRouteHTTPMatchHeader{ - Name: header["name"].(string), + Name: header["name"].(string), Present: header["present"].(bool), - Exact: header["exact"].(string), - Prefix: header["prefix"].(string), - Suffix: header["suffix"].(string), - Regex: header["regex"].(string), - Invert: header["present"].(bool), + Exact: header["exact"].(string), + Prefix: header["prefix"].(string), + Suffix: header["suffix"].(string), + Regex: header["regex"].(string), + Invert: header["present"].(bool), } headers[index] = *matchHeader } @@ -275,11 +273,11 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e serviceRoutesList[indx].Match = matchRoute //serviceRoutesList[indx].Destination = destination } - configEntry.Routes = serviceRoutesList + configEntry.Routes = serviceRoutesList } - + return configEntry, nil } func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { - + return nil } From 959a66e422f35277522f00ecbfb3eb223a71bdba Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 11:48:23 +0530 Subject: [PATCH 59/89] decode --- ...urce_consul_config_entry_service_router.go | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index e141f2ae..6a7d7c91 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -6,6 +6,7 @@ package consul import ( consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "time" ) type serviceRouter struct{} @@ -148,10 +149,10 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Type: schema.TypeString, }, "request_timeout": { - Type: schema.TypeInt, + Type: schema.TypeString, }, "idle_timeout": { - Type: schema.TypeInt, + Type: schema.TypeString, }, "num_retries": { Type: schema.TypeInt, @@ -271,7 +272,28 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e serviceRouteHTTPMatch.QueryParam = queryParamList matchRoute.HTTP = serviceRouteHTTPMatch serviceRoutesList[indx].Match = matchRoute - //serviceRoutesList[indx].Destination = destination + var destination *consulapi.ServiceRouteDestination + destination = new(consulapi.ServiceRouteDestination) + destinationList := (routListMap["destination"].(*schema.Set)).List() + if len(destinationList) > 0 { + destinationMap := destinationList[0].(map[string]interface{}) + destination.Service = destinationMap["service"].(string) + destination.ServiceSubset = destinationMap["service_subset"].(string) + destination.Namespace = destinationMap["namespace"].(string) + destination.Partition = destinationMap["partition"].(string) + destination.PrefixRewrite = destinationMap["prefix_rewrite"].(string) + requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) + if err != nil { + return nil, err + } + destination.RequestTimeout = requestTimeout + idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) + if err != nil { + return nil, err + } + destination.IdleTimeout = idleTimeout + } + serviceRoutesList[indx].Destination = destination } configEntry.Routes = serviceRoutesList } From 1147415e2c4f8201b56b14c06f346ad302874311 Mon Sep 17 00:00:00 2001 From: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:07:24 +0530 Subject: [PATCH 60/89] Update consul/resource_consul_config_entry_service_defaults.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémi Lapeyre --- consul/resource_consul_config_entry_service_defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 710f75f3..f836cb35 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -452,7 +452,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } } - getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) *consulapi.EnvoyExtension { + getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) consulapi.EnvoyExtension { return &consulapi.EnvoyExtension{ Name: envoyExtensionMap["name"].(string), Required: envoyExtensionMap["required"].(bool), From 9935559875339b0f88b17dc46c8db65320057425 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 12:07:58 +0530 Subject: [PATCH 61/89] schema fix --- ...ce_consul_config_entry_service_defaults.go | 119 +++++++++++++++++- 1 file changed, 115 insertions(+), 4 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 710f75f3..4b6af06d 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -22,7 +22,7 @@ func (s *serviceDefaults) GetDescription() string { } func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { - upstreamConfigSchema := &schema.Resource{ + upstreamConfigSchemaOverrides := &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -139,7 +139,118 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { }, }, } - + upstreamConfigSchemaDefaults := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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, + }, + "envoy_cluster_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.", + }, + }, + } return map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -189,13 +300,13 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { "overrides": { Type: schema.TypeList, Optional: true, - Elem: upstreamConfigSchema, + Elem: upstreamConfigSchemaOverrides, Description: "Specifies options that override the default upstream configurations for individual upstreams.", }, "defaults": { Type: schema.TypeSet, Optional: true, - Elem: upstreamConfigSchema, + 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.", }, }, From dc0e5a80b13ce063448e398210a637ac251f1fd2 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 12:14:59 +0530 Subject: [PATCH 62/89] fix schema --- ...ce_consul_config_entry_service_defaults.go | 41 ++++--------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 4b6af06d..fc814835 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -48,10 +48,6 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { Type: schema.TypeString, Optional: true, }, - "envoy_cluster_json": { - Type: schema.TypeString, - Optional: true, - }, "protocol": { Type: schema.TypeString, Optional: true, @@ -141,29 +137,10 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { } upstreamConfigSchemaDefaults := &schema.Resource{ Schema: map[string]*schema.Schema{ - "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, }, - "envoy_cluster_json": { - Type: schema.TypeString, - Optional: true, - }, "protocol": { Type: schema.TypeString, Optional: true, @@ -536,15 +513,13 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, getUpstreamConfig := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { upstreamConfig := &consulapi.UpstreamConfig{ - Name: upstreamConfigMap["name"].(string), - Partition: upstreamConfigMap["partition"].(string), - Namespace: upstreamConfigMap["namespace"].(string), - Peer: upstreamConfigMap["peer"].(string), - EnvoyListenerJSON: upstreamConfigMap["envoy_listener_json"].(string), - EnvoyClusterJSON: upstreamConfigMap["envoy_cluster_json"].(string), - Protocol: upstreamConfigMap["protocol"].(string), - ConnectTimeoutMs: upstreamConfigMap["connect_timeout_ms"].(int), - Limits: getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})), + Name: upstreamConfigMap["name"].(string), + Partition: upstreamConfigMap["partition"].(string), + Namespace: upstreamConfigMap["namespace"].(string), + Peer: upstreamConfigMap["peer"].(string), + Protocol: upstreamConfigMap["protocol"].(string), + ConnectTimeoutMs: upstreamConfigMap["connect_timeout_ms"].(int), + Limits: getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})), } passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) if err != nil { @@ -684,8 +659,6 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error upstreamConfig["partition"] = elem.Partition upstreamConfig["namespace"] = elem.Namespace upstreamConfig["peer"] = elem.Peer - upstreamConfig["envoy_listener_json"] = elem.EnvoyListenerJSON - upstreamConfig["envoy_cluster_json"] = elem.EnvoyClusterJSON upstreamConfig["protocol"] = elem.Protocol upstreamConfig["connect_timeout_ms"] = elem.ConnectTimeoutMs limits := make([]map[string]interface{}, 1) From 4e35678e1f7d2b18c77036de69f89821dc6a3e3d Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 12:17:03 +0530 Subject: [PATCH 63/89] fix pointeR --- consul/resource_consul_config_entry_service_defaults.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 0031ba1f..e2ae9ef6 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -539,7 +539,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) consulapi.EnvoyExtension { - return &consulapi.EnvoyExtension{ + return consulapi.EnvoyExtension{ Name: envoyExtensionMap["name"].(string), Required: envoyExtensionMap["required"].(bool), Arguments: envoyExtensionMap["arguments"].(map[string]interface{}), @@ -613,7 +613,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, for _, elem := range d.Get("envoy_extensions").([]interface{}) { envoyExtensionMap := elem.(map[string]interface{}) - configEntry.EnvoyExtensions = append(configEntry.EnvoyExtensions, *getEnvoyExtension(envoyExtensionMap)) + configEntry.EnvoyExtensions = append(configEntry.EnvoyExtensions, getEnvoyExtension(envoyExtensionMap)) } destinationList := d.Get("destination").(*schema.Set).List() From 3deb4455959707c85b48283d915dd0c3d62543ae Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 12:46:21 +0530 Subject: [PATCH 64/89] added nil checks --- ...ce_consul_config_entry_service_defaults.go | 212 ++++++++++++------ 1 file changed, 140 insertions(+), 72 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index e2ae9ef6..237cad2f 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -436,23 +436,43 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { 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), - Namespace: d.Get("namespace").(string), - Protocol: d.Get("protocol").(string), - BalanceInboundConnections: d.Get("balance_inbound_connections").(string), - LocalConnectTimeoutMs: d.Get("local_connect_timeout_ms").(int), - MaxInboundConnections: d.Get("max_inbound_connections").(int), - LocalRequestTimeoutMs: d.Get("local_request_timeout_ms").(int), - ExternalSNI: d.Get("external_sni").(string), - Mode: consulapi.ProxyMode(d.Get("mode").(string)), - MutualTLSMode: consulapi.MutualTLSMode(d.Get("mutual_tls_mode").(string)), - Meta: map[string]string{}, + 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{} - for k, v := range d.Get("meta").(map[string]interface{}) { - configEntry.Meta[k] = v.(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 { @@ -521,40 +541,63 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, ConnectTimeoutMs: upstreamConfigMap["connect_timeout_ms"].(int), Limits: getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})), } - passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) - if err != nil { - return nil, err + 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) } - upstreamConfig.PassiveHealthCheck = passiveHealthCheck - upstreamConfig.MeshGateway = *getMeshGateway(upstreamConfigMap["mesh_gateway"]) - upstreamConfig.BalanceOutboundConnections = upstreamConfigMap["balance_outbound_connections"].(string) return upstreamConfig, nil } getTransparentProxy := func(transparentProxy map[string]interface{}) *consulapi.TransparentProxyConfig { - return &consulapi.TransparentProxyConfig{ - OutboundListenerPort: transparentProxy["outbound_listener_port"].(int), - DialedDirectly: transparentProxy["dialed_directly"].(bool), + 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 { - return consulapi.EnvoyExtension{ - Name: envoyExtensionMap["name"].(string), - Required: envoyExtensionMap["required"].(bool), - Arguments: envoyExtensionMap["arguments"].(map[string]interface{}), - ConsulVersion: envoyExtensionMap["consul_version"].(string), - EnvoyVersion: envoyExtensionMap["envoy_version"].(string), + 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{ - Port: destinationMap["port"].(int), + destination := &consulapi.DestinationConfig{} + if destinationMap["port"] != nil { + destination.Port = destinationMap["port"].(int) } - for _, addr := range destinationMap["addresses"].([]interface{}) { - destination.Addresses = append(destination.Addresses, addr.(string)) + if destinationMap["addresses"] != nil { + for _, addr := range destinationMap["addresses"].([]interface{}) { + destination.Addresses = append(destination.Addresses, addr.(string)) + } } return destination } @@ -562,20 +605,31 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, } getExposePath := func(exposePathMap map[string]interface{}) *consulapi.ExposePath { - return &consulapi.ExposePath{ - Path: exposePathMap["path"].(string), - LocalPathPort: exposePathMap["local_path_port"].(int), - ListenerPort: exposePathMap["listener_port"].(int), - Protocol: exposePathMap["protocol"].(string), + 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{ - Checks: exposeMap["checks"].(bool), + exposeConfig := consulapi.ExposeConfig{} + if exposeMap["checks"] != nil { + exposeConfig.Checks = exposeMap["checks"].(bool) } - for _, elem := range exposeMap["paths"].([]interface{}) { - exposeConfig.Paths = append(exposeConfig.Paths, *getExposePath(elem.(map[string]interface{}))) + if exposeMap["paths"] != nil { + for _, elem := range exposeMap["paths"].([]interface{}) { + exposeConfig.Paths = append(exposeConfig.Paths, *getExposePath(elem.(map[string]interface{}))) + } } return exposeConfig } @@ -584,50 +638,64 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, if len(upstreamConfigList) > 0 { configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} upstreamConfigMap := upstreamConfigList[0].(map[string]interface{}) - defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() - if len(defaultsUpstreamConfigMapList) > 0 { - defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) - if err != nil { - return nil, err + if upstreamConfigMap["defaults"] != nil { + defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() + if len(defaultsUpstreamConfigMapList) > 0 { + defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) + if err != nil { + return nil, err + } + configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig } - configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig } - overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) - var overrideUpstreamConfig []*consulapi.UpstreamConfig - for _, elem := range overrideUpstreamConfigList { - overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) - if err != nil { - return nil, err + if upstreamConfigMap["overrides"] != nil { + overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) + var overrideUpstreamConfig []*consulapi.UpstreamConfig + for _, elem := range overrideUpstreamConfigList { + overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) + if err != nil { + return nil, err + } + overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) } - overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) + configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig } - configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig } - 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("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) + } } - for _, elem := range d.Get("envoy_extensions").([]interface{}) { - envoyExtensionMap := elem.(map[string]interface{}) - configEntry.EnvoyExtensions = append(configEntry.EnvoyExtensions, getEnvoyExtension(envoyExtensionMap)) + 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)) + } } - destinationList := d.Get("destination").(*schema.Set).List() - if len(destinationList) > 0 { - configEntry.Destination = getDestination(destinationList[0].(map[string]interface{})) + 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 v := getMeshGateway(d.Get("mesh_gateway")); v != nil { - configEntry.MeshGateway = *v + if d.Get("mesh_gateway") != nil { + if v := getMeshGateway(d.Get("mesh_gateway")); v != nil { + configEntry.MeshGateway = *v + } } - exposeList := d.Get("expose").(*schema.Set).List() - if len(exposeList) > 0 { - configEntry.Expose = getExpose(exposeList[0].(map[string]interface{})) + 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 From f25a6aab71261f9c3c1724895aba713783e43e83 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 13:24:48 +0530 Subject: [PATCH 65/89] fix schema and checks --- ...ce_consul_config_entry_service_defaults.go | 103 ++++++++++++++---- ...l_config_entry_service_defaults_ce_test.go | 82 +++++++------- 2 files changed, 124 insertions(+), 61 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 237cad2f..27539a78 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -5,10 +5,9 @@ package consul import ( "fmt" - "time" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "time" ) type serviceDefaults struct{} @@ -137,10 +136,6 @@ func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { } upstreamConfigSchemaDefaults := &schema.Resource{ Schema: map[string]*schema.Schema{ - "envoy_listener_json": { - Type: schema.TypeString, - Optional: true, - }, "protocol": { Type: schema.TypeString, Optional: true, @@ -531,15 +526,55 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return nil } - getUpstreamConfig := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { - upstreamConfig := &consulapi.UpstreamConfig{ - Name: upstreamConfigMap["name"].(string), - Partition: upstreamConfigMap["partition"].(string), - Namespace: upstreamConfigMap["namespace"].(string), - Peer: upstreamConfigMap["peer"].(string), - Protocol: upstreamConfigMap["protocol"].(string), - ConnectTimeoutMs: upstreamConfigMap["connect_timeout_ms"].(int), - Limits: getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})), + 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"]) @@ -641,7 +676,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, if upstreamConfigMap["defaults"] != nil { defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() if len(defaultsUpstreamConfigMapList) > 0 { - defaultsUpstreamConfig, err := getUpstreamConfig(defaultsUpstreamConfigMapList[0].(map[string]interface{})) + defaultsUpstreamConfig, err := getUpstreamConfigDefaults(defaultsUpstreamConfigMapList[0].(map[string]interface{})) if err != nil { return nil, err } @@ -653,7 +688,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) var overrideUpstreamConfig []*consulapi.UpstreamConfig for _, elem := range overrideUpstreamConfigList { - overrideUpstreamConfigElem, err := getUpstreamConfig(elem.(map[string]interface{})) + overrideUpstreamConfigElem, err := getUpstreamConfigOverrides(elem.(map[string]interface{})) if err != nil { return nil, err } @@ -721,7 +756,7 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error sw.set("balance_inbound_connections", sd.BalanceInboundConnections) sw.set("mode", sd.Mode) - getUpstreamConfig := func(elem *consulapi.UpstreamConfig) map[string]interface{} { + getUpstreamConfigOverrides := func(elem *consulapi.UpstreamConfig) map[string]interface{} { upstreamConfig := make(map[string]interface{}) upstreamConfig["name"] = elem.Name upstreamConfig["partition"] = elem.Partition @@ -753,16 +788,44 @@ func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error 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, getUpstreamConfig(elem)) + overrides = append(overrides, getUpstreamConfigOverrides(elem)) } upstreamConfig := make(map[string]interface{}) upstreamConfig["overrides"] = overrides defaultsSlice := make([]map[string]interface{}, 1) - defaultsSlice[0] = getUpstreamConfig(sd.UpstreamConfig.Defaults) + defaultsSlice[0] = getUpstreamConfigDefaults(sd.UpstreamConfig.Defaults) upstreamConfig["defaults"] = defaultsSlice upstreamConfigSlice := make([]map[string]interface{}, 1) upstreamConfigSlice[0] = upstreamConfig diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go index 1ad9be3e..7c21ce2c 100644 --- a/consul/resource_consul_config_entry_service_defaults_ce_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -64,47 +64,47 @@ func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { 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.384337465.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.interval", "19s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.interval", "19s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.protocol", "http"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.interval", "6h38m20s"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.384337465.defaults.375700018.passive_health_check.2909148994.base_ejection_time", "8h25m9s"), + 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"), From c1ac7fd58f3e00590c5d1833e2a055824c2488b2 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 14:49:56 +0530 Subject: [PATCH 66/89] added nil checks in service splitter --- ...ce_consul_config_entry_service_splitter.go | 94 ++++++++++--------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/consul/resource_consul_config_entry_service_splitter.go b/consul/resource_consul_config_entry_service_splitter.go index f30a9ad6..2ad886db 100644 --- a/consul/resource_consul_config_entry_service_splitter.go +++ b/consul/resource_consul_config_entry_service_splitter.go @@ -141,58 +141,68 @@ func (s *serviceSplitter) GetSchema() map[string]*schema.Schema { func (s *serviceSplitter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { configEntry := &consulapi.ServiceSplitterConfigEntry{ - Kind: consulapi.ServiceSplitter, - Name: d.Get("name").(string), - Partition: d.Get("partition").(string), - Namespace: d.Get("namespace").(string), - Meta: map[string]string{}, + Kind: consulapi.ServiceSplitter, + Name: d.Get("name").(string), + Meta: map[string]string{}, } - for k, v := range d.Get("meta").(map[string]interface{}) { - configEntry.Meta[k] = v.(string) + if d.Get("namespace") != nil { + configEntry.Namespace = d.Get("namespace").(string) } - for _, raw := range d.Get("splits").([]interface{}) { - s := raw.(map[string]interface{}) - split := consulapi.ServiceSplit{ - Weight: float32(s["weight"].(float64)), - Service: s["service"].(string), - ServiceSubset: s["service_subset"].(string), - Namespace: s["namespace"].(string), - Partition: s["partition"].(string), - RequestHeaders: &consulapi.HTTPHeaderModifiers{ - Add: map[string]string{}, - Set: map[string]string{}, - Remove: []string{}, - }, - ResponseHeaders: &consulapi.HTTPHeaderModifiers{ - Add: map[string]string{}, - Set: map[string]string{}, - Remove: []string{}, - }, + if d.Get("partition") != nil { + configEntry.Partition = d.Get("partition").(string) + } + + if d.Get("meta") != nil { + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) } + } - addHeaders := func(modifier *consulapi.HTTPHeaderModifiers, path string) { - elems := s[path].([]interface{}) - if len(elems) == 0 { - return + if d.Get("splits") != nil { + for _, raw := range d.Get("splits").([]interface{}) { + s := raw.(map[string]interface{}) + split := consulapi.ServiceSplit{ + Weight: float32(s["weight"].(float64)), + Service: s["service"].(string), + ServiceSubset: s["service_subset"].(string), + Namespace: s["namespace"].(string), + Partition: s["partition"].(string), + RequestHeaders: &consulapi.HTTPHeaderModifiers{ + Add: map[string]string{}, + Set: map[string]string{}, + Remove: []string{}, + }, + ResponseHeaders: &consulapi.HTTPHeaderModifiers{ + Add: map[string]string{}, + Set: map[string]string{}, + Remove: []string{}, + }, } - headers := elems[0].(map[string]interface{}) - for k, v := range headers["add"].(map[string]interface{}) { - modifier.Add[k] = v.(string) - } - for k, v := range headers["set"].(map[string]interface{}) { - modifier.Set[k] = v.(string) - } - for _, v := range headers["remove"].([]interface{}) { - modifier.Remove = append(modifier.Remove, v.(string)) + addHeaders := func(modifier *consulapi.HTTPHeaderModifiers, path string) { + elems := s[path].([]interface{}) + if len(elems) == 0 { + return + } + + headers := elems[0].(map[string]interface{}) + for k, v := range headers["add"].(map[string]interface{}) { + modifier.Add[k] = v.(string) + } + for k, v := range headers["set"].(map[string]interface{}) { + modifier.Set[k] = v.(string) + } + for _, v := range headers["remove"].([]interface{}) { + modifier.Remove = append(modifier.Remove, v.(string)) + } } - } - addHeaders(split.RequestHeaders, "request_headers") - addHeaders(split.ResponseHeaders, "response_headers") + addHeaders(split.RequestHeaders, "request_headers") + addHeaders(split.ResponseHeaders, "response_headers") - configEntry.Splits = append(configEntry.Splits, split) + configEntry.Splits = append(configEntry.Splits, split) + } } return configEntry, nil From 3309664fb3e71afee2aa22f2bc77e6bfee96262b Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 14:53:57 +0530 Subject: [PATCH 67/89] fix initializatin --- consul/resource_consul_config_entry_service_splitter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consul/resource_consul_config_entry_service_splitter.go b/consul/resource_consul_config_entry_service_splitter.go index 2ad886db..aa958866 100644 --- a/consul/resource_consul_config_entry_service_splitter.go +++ b/consul/resource_consul_config_entry_service_splitter.go @@ -248,7 +248,7 @@ func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } headers["set"] = set - remove := []interface{}{} + var remove []interface{} for _, v := range modifier.Remove { remove = append(remove, v) } From b75bce6378206bd6397c1327576046b9acc4517d Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 15:01:02 +0530 Subject: [PATCH 68/89] fix ee tests --- ...l_config_entry_service_defaults_ee_test.go | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go index f804a659..9d4032f9 100644 --- a/consul/resource_consul_config_entry_service_defaults_ee_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ee_test.go @@ -8,11 +8,11 @@ import ( "testing" ) -func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { +func TestAccConsulServiceDefaultsConfiEEEntryTest(t *testing.T) { providers, _ := startTestServer(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, Providers: providers, Steps: []resource.TestStep{ { @@ -61,54 +61,54 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { 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.foo", "namespace", "namespace2"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "partition", "partition2"), + 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.1485775592.overrides.0.name", "backend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.connect_timeout_ms", "500"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.0.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.name", "frontend"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.protocol", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_connections", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_pending_requests", "1900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.interval", "19"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_failures", "8"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.enforcing_consecutive_5xx", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.max_ejection_percent", "10"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.overrides.1.passive_health_check.749601092.base_ejection_time", "30"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.protocol", "http"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.connect_timeout_ms", "5000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.mesh_gateway.3192341522.mode", "tcp"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.balance_outbound_connections", "exact_balance"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_connections", "1000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_pending_requests", "9000"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.limits.3460439324.max_concurrent_requests", "2900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.interval", "23900"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_failures", "29030"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.enforcing_consecutive_5xx", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.max_ejection_percent", "12"), - resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.1485775592.defaults.2638836468.passive_health_check.2313231934.base_ejection_time", "30309"), + 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"), @@ -141,7 +141,7 @@ func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { }) } -// Destination and Upstream Config are exlusive. +// Destination and Upstream Config are exclusive. const testConsulServiceDefaultsConfigEntryWithDestinationEE = ` resource "consul_config_entry_service_defaults" "foo" { name = "service-defaults-test-1" From d56fe7354c0aaa4558393186d8842976cd8aaee4 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 17:36:51 +0530 Subject: [PATCH 69/89] fix tests --- ...ce_consul_config_entry_service_resolver.go | 166 ++++++++++++------ ...l_config_entry_service_resolver_ce_test.go | 48 ++--- 2 files changed, 140 insertions(+), 74 deletions(-) diff --git a/consul/resource_consul_config_entry_service_resolver.go b/consul/resource_consul_config_entry_service_resolver.go index cf7c9a6c..4fede46d 100644 --- a/consul/resource_consul_config_entry_service_resolver.go +++ b/consul/resource_consul_config_entry_service_resolver.go @@ -4,9 +4,14 @@ package consul import ( + "bytes" "fmt" consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "reflect" + "sort" + "strings" "time" ) @@ -57,7 +62,7 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { Description: "Specifies the timeout duration for receiving an HTTP response from this service.", }, "subsets": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Description: "Specifies names for custom service subsets and the conditions under which service instances belong to each subset.", Elem: &schema.Resource{ @@ -65,7 +70,7 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { "name": { Type: schema.TypeString, Required: true, - Description: "Name of subset", + Description: "Name of subset.", }, "filter": { Type: schema.TypeString, @@ -130,7 +135,7 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { }, }, "failover": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Description: "Specifies controls for rerouting traffic to an alternate pool of service instances if the target service fails.", Elem: &schema.Resource{ @@ -138,7 +143,7 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { "subset_name": { Type: schema.TypeString, Required: true, - Description: "Name of subset", + Description: "Name of subset.", }, "service": { Type: schema.TypeString, @@ -161,9 +166,11 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { Description: "Specifies the sameness group at the failover location where the failover services are deployed.", }, "datacenters": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, Description: "Specifies an ordered list of datacenters at the failover location to attempt connections to during a failover scenario. When Consul cannot establish a connection with the first datacenter in the list, it proceeds sequentially until establishing a connection with another datacenter.", }, "targets": { @@ -207,6 +214,7 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { }, }, }, + Set: resourceConsulConfigEntryServiceResolverFailoverSetHash, }, "load_balancer": { Type: schema.TypeSet, @@ -310,6 +318,56 @@ func (s *serviceResolver) GetSchema() map[string]*schema.Schema { } } +func resourceConsulConfigEntryServiceResolverFailoverSetHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + if m["subset_name"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["subset_name"].(string))) + } + if m["service"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["service"].(string))) + } + if m["service_subset"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["service_subset"].(string))) + } + if m["namespace"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["namespace"].(string))) + } + if m["sameness_group"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["sameness_group"].(string))) + } + if m["datacenters"] != nil { + datacenters := make([]string, 0) + if strings.HasPrefix(reflect.ValueOf(m["datacenters"]).String(), "<[]interface") { + for _, v := range m["datacenters"].([]interface{}) { + datacenters = append(datacenters, v.(string)) + } + } else { + for _, v := range m["datacenters"].([]string) { + datacenters = append(datacenters, v) + } + } + sort.Strings(datacenters) + for _, v := range datacenters { + buf.WriteString(fmt.Sprintf("%s-", v)) + } + } + if m["targets"] != nil { + for _, target := range m["targets"].([]interface{}) { + var keys []string + targetMap := target.(map[string]interface{}) + for k, _ := range targetMap { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + buf.WriteString(fmt.Sprintf("%s:%s-", k, targetMap[k].(string))) + } + } + } + return hashcode.String(buf.String()) +} + func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { configEntry := &consulapi.ServiceResolverConfigEntry{ Kind: consulapi.ServiceResolver, @@ -337,7 +395,7 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, subsets := make(map[string]consulapi.ServiceResolverSubset) - subsetsList := d.Get("subsets").([]interface{}) + subsetsList := d.Get("subsets").(*schema.Set).List() for _, subset := range subsetsList { subsetMap := subset.(map[string]interface{}) var serviceResolverSubset consulapi.ServiceResolverSubset @@ -363,7 +421,7 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, configEntry.Redirect = serviceResolverRedirect } - failoverList := d.Get("failover").([]interface{}) + failoverList := d.Get("failover").(*schema.Set).List() failover := make(map[string]consulapi.ServiceResolverFailover) for _, failoverElem := range failoverList { failoverMap := failoverElem.(map[string]interface{}) @@ -380,34 +438,40 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, if value, ok := failoverMap["sameness_group"]; ok { serviceResolverFailover.SamenessGroup = value.(string) } - if value, ok := failoverMap["datacenter"]; ok { - serviceResolverFailover.Datacenters = value.([]string) - } - serviceResolverFailoverTargets := make([]consulapi.ServiceResolverFailoverTarget, len(failoverMap["targets"].([]interface{}))) - for indx, target := range failoverMap["targets"].([]interface{}) { - targetElem := target.(map[string]interface{}) - var serviceResolverFailoverTarget consulapi.ServiceResolverFailoverTarget - if value, ok := targetElem["service"]; ok { - serviceResolverFailoverTarget.Service = value.(string) - } - if value, ok := targetElem["service_subset"]; ok { - serviceResolverFailoverTarget.ServiceSubset = value.(string) - } - if value, ok := targetElem["namespace"]; ok { - serviceResolverFailoverTarget.Namespace = value.(string) - } - if value, ok := targetElem["partition"]; ok { - serviceResolverFailoverTarget.Partition = value.(string) - } - if value, ok := targetElem["datacenter"]; ok { - serviceResolverFailoverTarget.Datacenter = value.(string) + if value, ok := failoverMap["datacenters"]; ok { + datacenters := make([]string, 0) + for _, v := range value.([]interface{}) { + datacenters = append(datacenters, v.(string)) } - if value, ok := targetElem["peer"]; ok { - serviceResolverFailoverTarget.Peer = value.(string) + serviceResolverFailover.Datacenters = datacenters + } + if (failoverMap["targets"] != nil) && len(failoverMap["targets"].([]interface{})) > 0 { + serviceResolverFailoverTargets := make([]consulapi.ServiceResolverFailoverTarget, len(failoverMap["targets"].([]interface{}))) + for indx, target := range failoverMap["targets"].([]interface{}) { + targetElem := target.(map[string]interface{}) + var serviceResolverFailoverTarget consulapi.ServiceResolverFailoverTarget + if value, ok := targetElem["service"]; ok { + serviceResolverFailoverTarget.Service = value.(string) + } + if value, ok := targetElem["service_subset"]; ok { + serviceResolverFailoverTarget.ServiceSubset = value.(string) + } + if value, ok := targetElem["namespace"]; ok { + serviceResolverFailoverTarget.Namespace = value.(string) + } + if value, ok := targetElem["partition"]; ok { + serviceResolverFailoverTarget.Partition = value.(string) + } + if value, ok := targetElem["datacenter"]; ok { + serviceResolverFailoverTarget.Datacenter = value.(string) + } + if value, ok := targetElem["peer"]; ok { + serviceResolverFailoverTarget.Peer = value.(string) + } + serviceResolverFailoverTargets[indx] = serviceResolverFailoverTarget } - serviceResolverFailoverTargets[indx] = serviceResolverFailoverTarget + serviceResolverFailover.Targets = serviceResolverFailoverTargets } - serviceResolverFailover.Targets = serviceResolverFailoverTargets failover[failoverMap["subset_name"].(string)] = serviceResolverFailover } configEntry.Failover = failover @@ -506,22 +570,25 @@ func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error sw.set("redirect", redirect) } - failover := make([]map[string]interface{}, len(sr.Failover)) - iter := 0 - for name, _ := range sr.Failover { + var failover *schema.Set + failover = new(schema.Set) + failover.F = resourceConsulConfigEntryServiceResolverFailoverSetHash + for name, failoverValue := range sr.Failover { failoverMap := make(map[string]interface{}) failoverMap["subset_name"] = name - failoverMap["service"] = sr.Failover[name].Service - failoverMap["service_subset"] = sr.Failover[name].ServiceSubset - failoverMap["namespace"] = sr.Failover[name].Namespace - failoverMap["sameness_group"] = sr.Failover[name].SamenessGroup - failoverDatacenters := make([]string, len(sr.Failover[name].Datacenters)) - for indx, fd := range sr.Failover[name].Datacenters { - failoverDatacenters[indx] = fd + failoverMap["service"] = failoverValue.Service + failoverMap["service_subset"] = failoverValue.ServiceSubset + failoverMap["namespace"] = failoverValue.Namespace + failoverMap["sameness_group"] = failoverValue.SamenessGroup + if len(failoverValue.Datacenters) > 0 { + failoverDatacenters := make([]string, len(failoverValue.Datacenters)) + for index, fd := range failoverValue.Datacenters { + failoverDatacenters[index] = fd + } + failoverMap["datacenters"] = failoverDatacenters } - failoverMap["datacenters"] = failoverDatacenters - failoverTargets := make([]map[string]interface{}, len(sr.Failover[name].Targets)) - for indx, ft := range sr.Failover[name].Targets { + failoverTargets := make([]interface{}, len(sr.Failover[name].Targets)) + for index, ft := range sr.Failover[name].Targets { failoverTargetMap := make(map[string]interface{}) failoverTargetMap["service"] = ft.Service failoverTargetMap["service_subset"] = ft.ServiceSubset @@ -529,11 +596,10 @@ func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error failoverTargetMap["partition"] = ft.Partition failoverTargetMap["datacenter"] = ft.Datacenter failoverTargetMap["peer"] = ft.Peer - failoverTargets[indx] = failoverTargetMap + failoverTargets[index] = failoverTargetMap } failoverMap["targets"] = failoverTargets - failover[iter] = failoverMap - iter++ + failover.Add(failoverMap) } sw.set("failover", failover) diff --git a/consul/resource_consul_config_entry_service_resolver_ce_test.go b/consul/resource_consul_config_entry_service_resolver_ce_test.go index 61b462f2..c9686913 100644 --- a/consul/resource_consul_config_entry_service_resolver_ce_test.go +++ b/consul/resource_consul_config_entry_service_resolver_ce_test.go @@ -24,12 +24,12 @@ func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "connect_timeout", "10s"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "request_timeout", "10s"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.#", "2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.name", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.filter", "Service.Meta.version == v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.0.only_passing", "true"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.name", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.filter", "Service.Meta.version == v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1420492792.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.1420492792.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.853348911.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.853348911.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.853348911.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "subsets.853348911.only_passing", "true"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "default_subset", "v1"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.#", "1"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.foo", "redirect.1000671749.datacenter", "dc1"), @@ -50,25 +50,25 @@ func TestAccConsulConfigEntryServiceResolverCETest(t *testing.T) { resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "connect_timeout", "10s"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "request_timeout", "10s"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.#", "2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.name", "v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.filter", "Service.Meta.version == v1"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.0.only_passing", "true"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.name", "v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.filter", "Service.Meta.version == v2"), - resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1420492792.name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1420492792.filter", "Service.Meta.version == v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.1420492792.only_passing", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.853348911.name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.853348911.filter", "Service.Meta.version == v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "subsets.853348911.only_passing", "true"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "default_subset", "v1"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.subset_name", "*"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.service", "backend"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.0.datacenters", "[\"dc3\", \"dc4\"]"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v2"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.service", "frontend"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.datacenters", "[\"dc2\"]"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1.subset_name", "v1"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.#", "1"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.service_subset", "v1"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.targets.0.datacenter", "dc1"), - //resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.2.datacenters", "[\"dc2\"]"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.#", "3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1078808137.subset_name", "*"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1078808137.service", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1078808137.datacenters.0", "dc3"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1078808137.datacenters.1", "dc4"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1326363731.subset_name", "v2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1326363731.service", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1326363731.datacenters.0", "dc2"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1420169321.subset_name", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1420169321.targets.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1420169321.targets.0.service_subset", "v1"), + resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "failover.1420169321.targets.0.datacenter", "dc1"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.policy", "ring_hash"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.#", "1"), resource.TestCheckResourceAttr("consul_config_entry_service_resolver.bar", "load_balancer.1867531597.ring_hash_config.1100849243.minimum_ring_size", "3"), From 0777493adba72ba644293819706e726094656b14 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 19:43:42 +0530 Subject: [PATCH 70/89] some fixes --- ...urce_consul_config_entry_service_router.go | 251 +++++++++++------- 1 file changed, 150 insertions(+), 101 deletions(-) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 6a7d7c91..4016289d 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -48,77 +48,97 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "routes": { Type: schema.TypeList, Description: "", + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "match": { Type: schema.TypeSet, Description: "", + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "http": { Type: schema.TypeSet, Description: "", + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "path_exact": { Type: schema.TypeString, + Optional: true, Description: "", }, "path_prefix": { Type: schema.TypeString, + Optional: true, Description: "", }, "path_regex": { Type: schema.TypeString, + Optional: true, Description: "", }, "methods": { - Type: schema.TypeList, - Elem: schema.TypeString, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, }, "header": { - Type: schema.TypeList, + Type: schema.TypeList, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "present": { - Type: schema.TypeBool, + Type: schema.TypeBool, + Optional: true, }, "exact": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "prefix": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "suffix": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "regex": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "invert": { - Type: schema.TypeBool, + Type: schema.TypeBool, + Optional: true, }, }, }, }, "query_param": { - Type: schema.TypeList, + Type: schema.TypeList, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "present": { - Type: schema.TypeBool, + Type: schema.TypeBool, + Optional: true, }, "exact": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "regex": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, }, }, @@ -130,78 +150,98 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { }, }, "destination": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "service": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "service_subset": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "namespace": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "partition": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "prefix_rewrite": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "request_timeout": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "idle_timeout": { - Type: schema.TypeString, + Type: schema.TypeString, + Optional: true, }, "num_retries": { - Type: schema.TypeInt, + Type: schema.TypeInt, + Optional: true, }, "retry_on_connect_failure": { - Type: schema.TypeBool, + Type: schema.TypeBool, + Optional: true, }, "retry_on": { - Type: schema.TypeList, - Elem: schema.TypeString, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, }, - "retry_on_status_code": { - Type: schema.TypeList, - Elem: schema.TypeInt, + "retry_on_status_codes": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeInt}, + Optional: true, }, "request_headers": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "add": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "set": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "remote": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, }, "response_headers": { - Type: schema.TypeMap, + Type: schema.TypeSet, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "add": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "set": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "remote": { - Type: schema.TypeMap, - Elem: schema.TypeString, + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, @@ -234,66 +274,75 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e serviceRoutesList := make([]consulapi.ServiceRoute, len(routeList)) for indx, r := range routeList { routListMap := r.(map[string]interface{}) - matchMap := routListMap["match"].(map[string]interface{}) - matchHTTP := matchMap["HTTP"].(map[string]interface{}) - var matchRoute *consulapi.ServiceRouteMatch - matchRoute = new(consulapi.ServiceRouteMatch) - var serviceRouteHTTPMatch *consulapi.ServiceRouteHTTPMatch - serviceRouteHTTPMatch = new(consulapi.ServiceRouteHTTPMatch) - serviceRouteHTTPMatch.PathExact = matchHTTP["path_exact"].(string) - serviceRouteHTTPMatch.PathPrefix = matchHTTP["path_prefix"].(string) - serviceRouteHTTPMatch.PathRegex = matchHTTP["path_regex"].(string) - serviceRouteHTTPMatch.Methods = matchHTTP["methods"].([]string) - var headers []consulapi.ServiceRouteHTTPMatchHeader - matchHeaders := matchHTTP["header"].([]interface{}) - for index, h := range matchHeaders { - header := h.(map[string]interface{}) - matchHeader := &consulapi.ServiceRouteHTTPMatchHeader{ - Name: header["name"].(string), - Present: header["present"].(bool), - Exact: header["exact"].(string), - Prefix: header["prefix"].(string), - Suffix: header["suffix"].(string), - Regex: header["regex"].(string), - Invert: header["present"].(bool), - } - headers[index] = *matchHeader - } - serviceRouteHTTPMatch.Header = headers - queryParam := matchHTTP["query_param"].([]interface{}) - queryParamList := make([]consulapi.ServiceRouteHTTPMatchQueryParam, len(queryParam)) - for index, q := range queryParam { - queryParamMap := q.(map[string]interface{}) - queryParamList[index].Name = queryParamMap["name"].(string) - queryParamList[index].Regex = queryParamMap["regex"].(string) - queryParamList[index].Present = queryParamMap["present"].(bool) - queryParamList[index].Exact = queryParamMap["exact"].(string) - } - serviceRouteHTTPMatch.QueryParam = queryParamList - matchRoute.HTTP = serviceRouteHTTPMatch - serviceRoutesList[indx].Match = matchRoute - var destination *consulapi.ServiceRouteDestination - destination = new(consulapi.ServiceRouteDestination) - destinationList := (routListMap["destination"].(*schema.Set)).List() - if len(destinationList) > 0 { - destinationMap := destinationList[0].(map[string]interface{}) - destination.Service = destinationMap["service"].(string) - destination.ServiceSubset = destinationMap["service_subset"].(string) - destination.Namespace = destinationMap["namespace"].(string) - destination.Partition = destinationMap["partition"].(string) - destination.PrefixRewrite = destinationMap["prefix_rewrite"].(string) - requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) - if err != nil { - return nil, err + matchList := routListMap["match"].(*schema.Set).List() + if len(matchList) > 0 { + matchMap := matchList[0].(map[string]interface{}) + matchHTTPMap := matchMap["http"].(*schema.Set).List() + if len(matchHTTPMap) > 0 { + matchHTTP := matchHTTPMap[0].(map[string]interface{}) + var matchRoute *consulapi.ServiceRouteMatch + matchRoute = new(consulapi.ServiceRouteMatch) + var serviceRouteHTTPMatch *consulapi.ServiceRouteHTTPMatch + serviceRouteHTTPMatch = new(consulapi.ServiceRouteHTTPMatch) + serviceRouteHTTPMatch.PathExact = matchHTTP["path_exact"].(string) + serviceRouteHTTPMatch.PathPrefix = matchHTTP["path_prefix"].(string) + serviceRouteHTTPMatch.PathRegex = matchHTTP["path_regex"].(string) + methods := make([]string, 0) + for _, v := range matchHTTP["methods"].([]interface{}) { + methods = append(methods, v.(string)) + } + serviceRouteHTTPMatch.Methods = methods + headers := make([]consulapi.ServiceRouteHTTPMatchHeader, 0) + matchHeaders := matchHTTP["header"].([]interface{}) + for _, h := range matchHeaders { + header := h.(map[string]interface{}) + matchHeader := &consulapi.ServiceRouteHTTPMatchHeader{ + Name: header["name"].(string), + Present: header["present"].(bool), + Exact: header["exact"].(string), + Prefix: header["prefix"].(string), + Suffix: header["suffix"].(string), + Regex: header["regex"].(string), + Invert: header["present"].(bool), + } + headers = append(headers, *matchHeader) + } + serviceRouteHTTPMatch.Header = headers + queryParam := matchHTTP["query_param"].([]interface{}) + queryParamList := make([]consulapi.ServiceRouteHTTPMatchQueryParam, len(queryParam)) + for index, q := range queryParam { + queryParamMap := q.(map[string]interface{}) + queryParamList[index].Name = queryParamMap["name"].(string) + queryParamList[index].Regex = queryParamMap["regex"].(string) + queryParamList[index].Present = queryParamMap["present"].(bool) + queryParamList[index].Exact = queryParamMap["exact"].(string) + } + serviceRouteHTTPMatch.QueryParam = queryParamList + matchRoute.HTTP = serviceRouteHTTPMatch + serviceRoutesList[indx].Match = matchRoute } - destination.RequestTimeout = requestTimeout - idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) - if err != nil { - return nil, err + var destination *consulapi.ServiceRouteDestination + destination = new(consulapi.ServiceRouteDestination) + destinationList := (routListMap["destination"].(*schema.Set)).List() + if len(destinationList) > 0 { + destinationMap := destinationList[0].(map[string]interface{}) + destination.Service = destinationMap["service"].(string) + destination.ServiceSubset = destinationMap["service_subset"].(string) + destination.Namespace = destinationMap["namespace"].(string) + destination.Partition = destinationMap["partition"].(string) + destination.PrefixRewrite = destinationMap["prefix_rewrite"].(string) + requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) + if err != nil { + return nil, err + } + destination.RequestTimeout = requestTimeout + idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) + if err != nil { + return nil, err + } + destination.IdleTimeout = idleTimeout } - destination.IdleTimeout = idleTimeout } - serviceRoutesList[indx].Destination = destination } configEntry.Routes = serviceRoutesList } From 92044ad32e1afa795f97cb57e0f8a23fc0b5fd0c Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 20:50:36 +0530 Subject: [PATCH 71/89] write --- ...urce_consul_config_entry_service_router.go | 118 +++++++++++++++++- 1 file changed, 114 insertions(+), 4 deletions(-) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 4016289d..36073cb1 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -4,6 +4,7 @@ package consul import ( + "fmt" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "time" @@ -215,8 +216,8 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "remote": { - Type: schema.TypeMap, + "remove": { + Type: schema.TypeList, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -238,7 +239,7 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "remote": { + "remove": { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -350,5 +351,114 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e } func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { - return nil + sr, ok := ce.(*consulapi.ServiceRouterConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceDefaults, ce.GetKind()) + } + + sw.set("name", sr.Name) + sw.set("partition", sr.Partition) + sw.set("namespace", sr.Namespace) + + meta := make(map[string]interface{}) + for k, v := range sr.Meta { + meta[k] = v + } + sw.set("meta", meta) + + routes := make([]interface{}, 0) + if len(sr.Routes) > 0 { + route := make(map[string]interface{}) + for _, routesValue := range sr.Routes { + match := make([]map[string]interface{}, 1) + match[0] = make(map[string]interface{}) + matchHTTP := make(map[string]interface{}) + matchHTTP["path_exact"] = routesValue.Match.HTTP.PathExact + matchHTTP["path_prefix"] = routesValue.Match.HTTP.PathPrefix + matchHTTP["path_regex"] = routesValue.Match.HTTP.PathRegex + matchHTTP["methods"] = routesValue.Match.HTTP.Methods + headerList := make([]map[string]interface{}, 0) + for _, headerValue := range routesValue.Match.HTTP.Header { + headerMap := make(map[string]interface{}) + headerMap["name"] = headerValue.Name + headerMap["present"] = headerValue.Present + headerMap["exact"] = headerValue.Exact + headerMap["prefix"] = headerValue.Prefix + headerMap["suffix"] = headerValue.Suffix + headerMap["regex"] = headerValue.Regex + headerMap["invert"] = headerValue.Invert + headerList = append(headerList, headerMap) + } + queryParamList := make([]map[string]interface{}, 0) + for _, queryParamValue := range routesValue.Match.HTTP.QueryParam { + queryParamMap := make(map[string]interface{}) + queryParamMap["name"] = queryParamValue.Name + queryParamMap["present"] = queryParamValue.Present + queryParamMap["exact"] = queryParamValue.Exact + queryParamMap["regex"] = queryParamValue.Regex + queryParamList = append(queryParamList, queryParamMap) + } + matchHTTP["header"] = headerList + matchHTTP["query_param"] = queryParamList + match[0]["http"] = matchHTTP + destination := make([]map[string]interface{}, 1) + destination[0] = make(map[string]interface{}) + destination[0]["service"] = routesValue.Destination.Service + destination[0]["service_subset"] = routesValue.Destination.ServiceSubset + destination[0]["namespace"] = routesValue.Destination.Namespace + destination[0]["partition"] = routesValue.Destination.Partition + destination[0]["prefix_rewrite"] = routesValue.Destination.PrefixRewrite + destination[0]["request_timeout"] = routesValue.Destination.RequestTimeout + destination[0]["idle_timeout"] = routesValue.Destination.IdleTimeout + destination[0]["num_retries"] = routesValue.Destination.NumRetries + destination[0]["retry_on_connect_failure"] = routesValue.Destination.RetryOnConnectFailure + destination[0]["retry_on"] = routesValue.Destination.RetryOn + destination[0]["retry_on_status_codes"] = routesValue.Destination.RetryOnStatusCodes + requestHeaders := make(map[string]interface{}) + requestHeaders["add"] = make(map[string]interface{}) + addMap := make(map[string]interface{}) + for k, v := range routesValue.Destination.RequestHeaders.Add { + addMap[k] = v + } + requestHeaders["add"] = addMap + setMap := make(map[string]interface{}) + requestHeaders["set"] = make(map[string]interface{}) + for k, v := range routesValue.Destination.RequestHeaders.Set { + setMap[k] = v + } + requestHeaders["set"] = setMap + requestHeaders["remove"] = make([]string, 0) + removeList := make([]string, 0) + for _, v := range routesValue.Destination.RequestHeaders.Remove { + removeList = append(removeList, v) + } + requestHeaders["remove"] = removeList + destination[0]["request_headers"] = requestHeaders + responseHeaders := make(map[string]interface{}) + responseHeaders["add"] = make(map[string]interface{}) + addMap = make(map[string]interface{}) + for k, v := range routesValue.Destination.ResponseHeaders.Add { + addMap[k] = v + } + responseHeaders["add"] = addMap + setMap = make(map[string]interface{}) + requestHeaders["set"] = make(map[string]interface{}) + for k, v := range routesValue.Destination.ResponseHeaders.Set { + setMap[k] = v + } + responseHeaders["set"] = setMap + responseHeaders["remove"] = make([]string, 0) + removeList = make([]string, 0) + for _, v := range routesValue.Destination.ResponseHeaders.Remove { + removeList = append(removeList, v) + } + responseHeaders["remove"] = removeList + destination[0]["response_headers"] = responseHeaders + route["match"] = match + route["destination"] = destination + } + routes = append(routes, route) + } + + sw.set("routes", routes) } From 8a4d3e4ccbbc4b266d03849315b6980bfaa71af0 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Tue, 3 Oct 2023 20:51:09 +0530 Subject: [PATCH 72/89] return nil --- consul/resource_consul_config_entry_service_router.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 36073cb1..406a6354 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -461,4 +461,6 @@ func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { } sw.set("routes", routes) + + return nil } From 8e469eef64e4a10d6a61bdc2fa7fdbc0c6a26088 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 08:47:24 +0530 Subject: [PATCH 73/89] fixes --- ...urce_consul_config_entry_service_router.go | 259 +++++++++++++----- ...sul_config_entry_service_router_ce_test.go | 74 +++++ 2 files changed, 266 insertions(+), 67 deletions(-) create mode 100644 consul/resource_consul_config_entry_service_router_ce_test.go diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 406a6354..336759a7 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -178,18 +178,22 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "request_timeout": { Type: schema.TypeString, Optional: true, + Default: "0s", }, "idle_timeout": { Type: schema.TypeString, Optional: true, + Default: "0s", }, "num_retries": { Type: schema.TypeInt, Optional: true, + Default: 0, }, "retry_on_connect_failure": { Type: schema.TypeBool, Optional: true, + Default: false, }, "retry_on": { Type: schema.TypeList, @@ -240,7 +244,7 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Elem: &schema.Schema{Type: schema.TypeString}, }, "remove": { - Type: schema.TypeMap, + Type: schema.TypeList, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -332,16 +336,121 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e destination.Namespace = destinationMap["namespace"].(string) destination.Partition = destinationMap["partition"].(string) destination.PrefixRewrite = destinationMap["prefix_rewrite"].(string) - requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) - if err != nil { - return nil, err + if destinationMap["request_timeout"] != "" { + requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) + if err != nil { + return nil, err + } + destination.RequestTimeout = requestTimeout + } + if destinationMap["idle_timeout"] != "" { + idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) + if err != nil { + return nil, err + } + destination.IdleTimeout = idleTimeout + } + destination.NumRetries = uint32(destinationMap["num_retries"].(int)) + destination.RetryOnConnectFailure = destinationMap["retry_on_connect_failure"].(bool) + retryOnList := make([]string, 0) + for _, v := range destinationMap["retry_on"].([]interface{}) { + retryOnList = append(retryOnList, v.(string)) + } + destination.RetryOn = retryOnList + retryOnCodes := make([]uint32, 0) + for _, v := range destinationMap["retry_on_status_codes"].([]interface{}) { + retryOnCodes = append(retryOnCodes, v.(uint32)) + } + destination.RetryOnStatusCodes = retryOnCodes + var requestMap *consulapi.HTTPHeaderModifiers + requestMap = new(consulapi.HTTPHeaderModifiers) + addMap := make(map[string]string) + setMap := make(map[string]string) + if destinationMap["request_headers"] != nil { + reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() + if len(reqHeadersList) > 0 { + destinationAddMap := reqHeadersList[0].(map[string]interface{})["add"] + if destinationAddMap != nil { + for k, v := range destinationAddMap.(map[string]string) { + addMap[k] = v + } + requestMap.Add = addMap + } + } + } + if destinationMap["request_headers"] != nil { + reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() + if len(reqHeadersList) > 0 { + destinationSetMap := reqHeadersList[0].(map[string]interface{})["set"] + if destinationSetMap != nil { + for k, v := range destinationSetMap.(map[string]string) { + setMap[k] = v + } + requestMap.Set = setMap + } + } + } + removeList := make([]string, 0) + if destinationMap["request_headers"] != nil { + reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() + if len(reqHeadersList) > 0 { + destinationRemoveList := reqHeadersList[0].(map[string]interface{})["remove"] + if destinationRemoveList != nil && len(destinationRemoveList.([]string)) > 0 { + for _, v := range destinationRemoveList.([]string) { + removeList = append(removeList, v) + } + } + } + } + if len(removeList) > 0 { + requestMap.Remove = removeList + } + destination.RequestHeaders = requestMap + var responseMap *consulapi.HTTPHeaderModifiers + responseMap = new(consulapi.HTTPHeaderModifiers) + addMap = make(map[string]string) + setMap = make(map[string]string) + if destinationMap["response_headers"] != nil { + resHeadersList := destinationMap["response_headers"].(*schema.Set).List() + if len(resHeadersList) > 0 { + destinationAddMap := resHeadersList[0].(map[string]interface{})["add"] + if destinationAddMap != nil { + for k, v := range destinationAddMap.(map[string]string) { + addMap[k] = v + } + responseMap.Add = addMap + } + } + } + if destinationMap["response_headers"] != nil { + resHeadersList := destinationMap["response_headers"].(*schema.Set).List() + if len(resHeadersList) > 0 { + destinationSetMap := resHeadersList[0].(map[string]interface{})["set"] + if destinationSetMap != nil { + for k, v := range destinationSetMap.(map[string]string) { + setMap[k] = v + } + responseMap.Set = setMap + } + } + } + removeList = make([]string, 0) + if destinationMap["response_headers"] != nil { + resHeadersList := destinationMap["response_headers"].(*schema.Set).List() + if len(resHeadersList) > 0 { + destinationRemoveList := resHeadersList[0].(map[string]interface{})["remove"] + if destinationRemoveList != nil && len(destinationRemoveList.([]string)) > 0 { + for _, v := range destinationRemoveList.([]string) { + removeList = append(removeList, v) + } + } + } } - destination.RequestTimeout = requestTimeout - idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) - if err != nil { - return nil, err + if len(removeList) > 0 { + responseMap.Remove = removeList } - destination.IdleTimeout = idleTimeout + destination.ResponseHeaders = responseMap + serviceRoutesList[indx].Destination = destination } } } @@ -366,17 +475,18 @@ func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { } sw.set("meta", meta) - routes := make([]interface{}, 0) + routes := make([]map[string]interface{}, 0) if len(sr.Routes) > 0 { route := make(map[string]interface{}) for _, routesValue := range sr.Routes { match := make([]map[string]interface{}, 1) match[0] = make(map[string]interface{}) - matchHTTP := make(map[string]interface{}) - matchHTTP["path_exact"] = routesValue.Match.HTTP.PathExact - matchHTTP["path_prefix"] = routesValue.Match.HTTP.PathPrefix - matchHTTP["path_regex"] = routesValue.Match.HTTP.PathRegex - matchHTTP["methods"] = routesValue.Match.HTTP.Methods + matchHTTP := make([]map[string]interface{}, 1) + matchHTTP[0] = make(map[string]interface{}) + matchHTTP[0]["path_exact"] = routesValue.Match.HTTP.PathExact + matchHTTP[0]["path_prefix"] = routesValue.Match.HTTP.PathPrefix + matchHTTP[0]["path_regex"] = routesValue.Match.HTTP.PathRegex + matchHTTP[0]["methods"] = routesValue.Match.HTTP.Methods headerList := make([]map[string]interface{}, 0) for _, headerValue := range routesValue.Match.HTTP.Header { headerMap := make(map[string]interface{}) @@ -398,62 +508,77 @@ func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { queryParamMap["regex"] = queryParamValue.Regex queryParamList = append(queryParamList, queryParamMap) } - matchHTTP["header"] = headerList - matchHTTP["query_param"] = queryParamList + matchHTTP[0]["header"] = headerList + matchHTTP[0]["query_param"] = queryParamList match[0]["http"] = matchHTTP destination := make([]map[string]interface{}, 1) destination[0] = make(map[string]interface{}) - destination[0]["service"] = routesValue.Destination.Service - destination[0]["service_subset"] = routesValue.Destination.ServiceSubset - destination[0]["namespace"] = routesValue.Destination.Namespace - destination[0]["partition"] = routesValue.Destination.Partition - destination[0]["prefix_rewrite"] = routesValue.Destination.PrefixRewrite - destination[0]["request_timeout"] = routesValue.Destination.RequestTimeout - destination[0]["idle_timeout"] = routesValue.Destination.IdleTimeout - destination[0]["num_retries"] = routesValue.Destination.NumRetries - destination[0]["retry_on_connect_failure"] = routesValue.Destination.RetryOnConnectFailure - destination[0]["retry_on"] = routesValue.Destination.RetryOn - destination[0]["retry_on_status_codes"] = routesValue.Destination.RetryOnStatusCodes - requestHeaders := make(map[string]interface{}) - requestHeaders["add"] = make(map[string]interface{}) - addMap := make(map[string]interface{}) - for k, v := range routesValue.Destination.RequestHeaders.Add { - addMap[k] = v - } - requestHeaders["add"] = addMap - setMap := make(map[string]interface{}) - requestHeaders["set"] = make(map[string]interface{}) - for k, v := range routesValue.Destination.RequestHeaders.Set { - setMap[k] = v - } - requestHeaders["set"] = setMap - requestHeaders["remove"] = make([]string, 0) - removeList := make([]string, 0) - for _, v := range routesValue.Destination.RequestHeaders.Remove { - removeList = append(removeList, v) - } - requestHeaders["remove"] = removeList - destination[0]["request_headers"] = requestHeaders - responseHeaders := make(map[string]interface{}) - responseHeaders["add"] = make(map[string]interface{}) - addMap = make(map[string]interface{}) - for k, v := range routesValue.Destination.ResponseHeaders.Add { - addMap[k] = v - } - responseHeaders["add"] = addMap - setMap = make(map[string]interface{}) - requestHeaders["set"] = make(map[string]interface{}) - for k, v := range routesValue.Destination.ResponseHeaders.Set { - setMap[k] = v - } - responseHeaders["set"] = setMap - responseHeaders["remove"] = make([]string, 0) - removeList = make([]string, 0) - for _, v := range routesValue.Destination.ResponseHeaders.Remove { - removeList = append(removeList, v) + if routesValue.Destination != nil { + destination[0]["service"] = routesValue.Destination.Service + destination[0]["service_subset"] = routesValue.Destination.ServiceSubset + destination[0]["namespace"] = routesValue.Destination.Namespace + destination[0]["partition"] = routesValue.Destination.Partition + destination[0]["prefix_rewrite"] = routesValue.Destination.PrefixRewrite + destination[0]["request_timeout"] = routesValue.Destination.RequestTimeout.String() + destination[0]["idle_timeout"] = routesValue.Destination.IdleTimeout.String() + destination[0]["num_retries"] = routesValue.Destination.NumRetries + destination[0]["retry_on_connect_failure"] = routesValue.Destination.RetryOnConnectFailure + destination[0]["retry_on"] = routesValue.Destination.RetryOn + destination[0]["retry_on_status_codes"] = routesValue.Destination.RetryOnStatusCodes + requestHeaders := make([]map[string]interface{}, 1) + requestHeaders[0] = make(map[string]interface{}) + addMap := make(map[string]interface{}) + if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Add != nil { + for k, v := range routesValue.Destination.RequestHeaders.Add { + addMap[k] = v + } + } + requestHeaders[0]["add"] = addMap + setMap := make(map[string]interface{}) + if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Set != nil { + for k, v := range routesValue.Destination.RequestHeaders.Set { + setMap[k] = v + } + } + requestHeaders[0]["set"] = setMap + removeList := make([]string, 0) + if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Remove != nil { + for _, v := range routesValue.Destination.RequestHeaders.Remove { + removeList = append(removeList, v) + } + } + if len(removeList) > 0 { + requestHeaders[0]["remove"] = removeList + } + destination[0]["request_headers"] = requestHeaders + responseHeaders := make([]map[string]interface{}, 1) + responseHeaders[0] = make(map[string]interface{}) + responseHeaders[0]["add"] = make(map[string]interface{}) + addMap = make(map[string]interface{}) + if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Add != nil { + for k, v := range routesValue.Destination.ResponseHeaders.Add { + addMap[k] = v + } + } + responseHeaders[0]["add"] = addMap + setMap = make(map[string]interface{}) + if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Set != nil { + for k, v := range routesValue.Destination.ResponseHeaders.Set { + setMap[k] = v + } + } + responseHeaders[0]["set"] = setMap + removeList = make([]string, 0) + if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Remove != nil { + for _, v := range routesValue.Destination.ResponseHeaders.Remove { + removeList = append(removeList, v) + } + } + if len(removeList) > 0 { + responseHeaders[0]["remove"] = removeList + } + destination[0]["response_headers"] = responseHeaders } - responseHeaders["remove"] = removeList - destination[0]["response_headers"] = responseHeaders route["match"] = match route["destination"] = destination } diff --git a/consul/resource_consul_config_entry_service_router_ce_test.go b/consul/resource_consul_config_entry_service_router_ce_test.go new file mode 100644 index 00000000..9dec2c9a --- /dev/null +++ b/consul/resource_consul_config_entry_service_router_ce_test.go @@ -0,0 +1,74 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceRouterCETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceRouterCE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.365255188.http.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.365255188.http.3609927257.path_prefix", "/admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.1670225453.retry_on_connect_failure", "false"), + ), + }, + }, + }) +} + +const testConsulConfigEntryServiceRouterCE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + + routes { + match { + http { + path_prefix = "/admin" + } + } + + destination { + service = consul_config_entry.admin_service_defaults.name + } + } +} +` From 58a2c7b8df876e99590b9cb1bf5f914a50741925 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 11:10:05 +0530 Subject: [PATCH 74/89] added description --- ...urce_consul_config_entry_service_router.go | 208 ++++++++++-------- 1 file changed, 121 insertions(+), 87 deletions(-) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index 336759a7..f11f5dc2 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -48,98 +48,112 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { }, "routes": { Type: schema.TypeList, - Description: "", + Description: "Defines the possible routes for L7 requests.", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "match": { Type: schema.TypeSet, - Description: "", + Description: "Describes a set of criteria that Consul compares incoming L7 traffic with.", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "http": { Type: schema.TypeSet, - Description: "", + Description: "Specifies a set of HTTP criteria used to evaluate incoming L7 traffic for matches.", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "path_exact": { Type: schema.TypeString, Optional: true, - Description: "", + Description: "Specifies the exact path to match on the HTTP request path.", }, "path_prefix": { Type: schema.TypeString, Optional: true, - Description: "", + Description: "Specifies the path prefix to match on the HTTP request path.", }, "path_regex": { Type: schema.TypeString, Optional: true, - Description: "", + Description: "Specifies a regular expression to match on the HTTP request path.", }, "methods": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, + Type: schema.TypeList, + Description: "Specifies HTTP methods that the match applies to.", + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, }, "header": { - Type: schema.TypeList, - Optional: true, + Type: schema.TypeList, + Optional: true, + Description: "Specifies information in the HTTP request header to match with.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Description: "Specifies the name of the HTTP header to match.", + Optional: true, }, "present": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Description: "Specifies that a request matches when the value in the Name field is present anywhere in the HTTP header.", }, "exact": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the header with the given name is this exact value.", }, "prefix": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the header with the given name has this prefix.", }, "suffix": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the header with the given name has this suffix.", }, "regex": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the header with the given name matches this regular expression.", }, "invert": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Description: "Specifies that the logic for the HTTP header match should be inverted.", }, }, }, }, "query_param": { - Type: schema.TypeList, - Optional: true, + Type: schema.TypeList, + Optional: true, + Description: "Specifies information to match to on HTTP query parameters.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Description: "Specifies the name of the HTTP query parameter to match.", + Optional: true, }, "present": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Description: "Specifies that a request matches when the value in the Name field is present anywhere in the HTTP query parameter.", }, "exact": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the query parameter with the given name is this exact value.", }, "regex": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies that a request matches when the query parameter with the given name matches this regular expression.", }, }, }, @@ -151,102 +165,122 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { }, }, "destination": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeSet, + Optional: true, + Description: "Specifies the target service to route matching requests to, as well as behavior for the request to follow when routed.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "service": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of the service to resolve.", }, "service_subset": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies a named subset of the given service to resolve instead of the one defined as that service's DefaultSubset in the service resolver configuration entry.", }, "namespace": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the Consul namespace to resolve the service from instead of the current namespace.", }, "partition": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies the Consul admin partition to resolve the service from instead of the current partition.", }, "prefix_rewrite": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "Specifies rewrites to the HTTP request path before proxying it to its final destination.", }, "request_timeout": { - Type: schema.TypeString, - Optional: true, - Default: "0s", + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: "Specifies the total amount of time permitted for the entire downstream request to be processed, including retry attempts.", }, "idle_timeout": { - Type: schema.TypeString, - Optional: true, - Default: "0s", + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: "Specifies the total amount of time permitted for the request stream to be idle.", }, "num_retries": { - Type: schema.TypeInt, - Optional: true, - Default: 0, + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Specifies the number of times to retry the request when a retry condition occurs.", }, "retry_on_connect_failure": { - Type: schema.TypeBool, - Optional: true, - Default: false, + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Specifies that connection failure errors that trigger a retry request.", }, "retry_on": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + Description: "Specifies a list of conditions for Consul to retry requests based on the response from an upstream service.", }, "retry_on_status_codes": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeInt}, - Optional: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeInt}, + Optional: true, + Description: "Specifies a list of integers for HTTP response status codes that trigger a retry request.", }, "request_headers": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeSet, + Optional: true, + Description: "Specifies a set of HTTP-specific header modification rules applied to requests routed with the service router.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "add": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeMap, + Description: "Defines a set of key-value pairs to add to the header. Use header names as the keys.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "set": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeMap, + Optional: true, + Description: "Defines a set of key-value pairs to add to the request header or to replace existing header values with.", + Elem: &schema.Schema{Type: schema.TypeString}, }, "remove": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Description: "Defines a list of headers to remove.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, }, "response_headers": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeSet, + Optional: true, + Description: "Specifies a set of HTTP-specific header modification rules applied to responses routed with the service router.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "add": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeMap, + Optional: true, + Description: "Defines a set of key-value pairs to add to the header. Use header names as the keys", + Elem: &schema.Schema{Type: schema.TypeString}, }, "set": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeMap, + Optional: true, + Description: "Defines a set of key-value pairs to add to the response header or to replace existing header values with", + Elem: &schema.Schema{Type: schema.TypeString}, }, "remove": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Optional: true, + Description: "Defines a list of headers to remove.", + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, From 30b50e385b18c97284a80f29be5a3128d7eb3d96 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 15:07:12 +0530 Subject: [PATCH 75/89] intentions --- ..._consul_config_entry_service_intentions.go | 541 ++++++++++++++++++ ...ce_consul_config_entry_service_splitter.go | 2 +- consul/resource_provider.go | 57 +- 3 files changed, 571 insertions(+), 29 deletions(-) create mode 100644 consul/resource_consul_config_entry_service_intentions.go diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go new file mode 100644 index 00000000..b0f36370 --- /dev/null +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -0,0 +1,541 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +type serviceIntentions struct{} + +func (s *serviceIntentions) GetKind() string { + return consulapi.ServiceIntentions +} + +func (s *serviceIntentions) GetDescription() string { + return "The `consul_service_intentions_config_entry` resource configures a [service intentions](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-intentions) that are configurations for controlling access between services in the service mesh. A single service intentions configuration entry specifies one destination service and one or more L4 traffic sources, L7 traffic sources, or combination of traffic sources." +} + +func (s *serviceIntentions) GetSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "Specifies a name of the destination service for all intentions defined in the configuration entry.", + Required: true, + ForceNew: true, + }, + "partition": { + Type: schema.TypeString, + Description: "Specifies the admin partition to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "namespace": { + Type: schema.TypeString, + Description: "Specifies the namespace to apply the configuration entry.", + Optional: true, + ForceNew: true, + }, + "meta": { + Type: schema.TypeMap, + Description: "Specifies key-value pairs to add to the KV store.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "jwt": { + Type: schema.TypeSet, + Description: "Specifies a JSON Web Token provider configured in a JWT provider configuration entry, as well as additional configurations for verifying a service's JWT before authorizing communication between services", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "providers": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies the names of one or more previously configured JWT provider configuration entries, which include the information necessary to validate a JSON web token.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "Specifies the name of a JWT provider defined in the Name field of the jwt-provider configuration entry.", + Optional: true, + }, + "verify_claims": { + Type: schema.TypeList, + Description: "Specifies additional token information to verify beyond what is configured in the JWT provider configuration entry.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies the path to the claim in the JSON web token.", + Elem: schema.Schema{Type: schema.TypeString}, + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the value to match on when verifying the the claim designated in path.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: "List of configurations that define intention sources and the authorization granted to the sources.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "Specifies the name of the source that the intention allows or denies traffic from.", + Optional: true, + }, + "peer": { + Type: schema.TypeString, + Description: "Specifies the name of a peered Consul cluster that the intention allows or denies traffic from", + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Description: "Specifies the traffic source namespace that the intention allows or denies traffic from.", + Optional: true, + }, + "partition": { + Type: schema.TypeString, + Description: "Specifies the name of an admin partition that the intention allows or denies traffic from.", + Optional: true, + }, + "sameness_group": { + Type: schema.TypeString, + Description: "Specifies the name of a sameness group that the intention allows or denies traffic from.", + Optional: true, + }, + "action": { + Type: schema.TypeString, + Description: "Specifies the action to take when the source sends traffic to the destination service.", + Optional: true, + }, + "permissions": { + Type: schema.TypeList, + Description: "Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Required: true, + Description: "Specifies the action to take when the source sends traffic to the destination service. The value is either allow or deny.", + Type: schema.TypeString, + }, + "http": { + Type: schema.TypeSet, + Required: true, + Description: "Specifies a set of HTTP-specific match criteria. ", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path_exact": { + Type: schema.TypeString, + Description: "Specifies an exact path to match on the HTTP request path.", + Optional: true, + }, + "path_prefix": { + Type: schema.TypeString, + Description: "Specifies a path prefix to match on the HTTP request path.", + Optional: true, + }, + "path_regex": { + Type: schema.TypeString, + Description: "Defines a regular expression to match on the HTTP request path.", + Optional: true, + }, + "methods": { + Type: schema.TypeList, + Description: "Specifies a list of HTTP methods.", + Optional: true, + Elem: schema.Schema{Type: schema.TypeString}, + }, + "headers": { + Type: schema.TypeList, + Description: "Specifies a header name and matching criteria for HTTP request headers.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Specifies the name of the header to match.", + }, + "present": { + Type: schema.TypeBool, + Default: false, + Optional: true, + Description: "Enables a match if the header configured in the Name field appears in the request. Consul matches on any value as long as the header key appears in the request.", + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a value for the header key set in the Name field. If the request header value matches the Exact value, Consul applies the permission.", + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a prefix value for the header key set in the Name field.", + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a suffix value for the header key set in the Name field.", + }, + "regex": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a regular expression pattern as the value for the header key set in the Name field.", + }, + "invert": { + Type: schema.TypeBool, + Optional: true, + Description: "Inverts the matching logic configured in the Header.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "precedence": { + Type: schema.TypeInt, + Description: "The Precedence field contains a read-only integer. Consul generates the value based on name configurations for the source and destination services.", + Optional: true, + }, + "type": { + Type: schema.TypeString, + Default: "consul", + Description: "Specifies the type of destination service that the configuration entry applies to.", + }, + "description": { + Type: schema.TypeString, + Description: "Specifies a description of the intention.", + Optional: true, + }, + "legacy_id": { + Type: schema.TypeString, + Description: "Read-only unique user ID (UUID) for the intention in the system.", + Optional: true, + }, + "legacy_meta": { + Type: schema.TypeMap, + Optional: true, + Description: "Read-only set of arbitrary key-value pairs to attach to the intention.", + Elem: schema.Schema{Type: schema.TypeString}, + }, + "legacy_create_time": { + Type: schema.TypeString, + Description: "Read-only timestamp for the intention creation.", + Optional: true, + }, + "legacy_update_time": { + Type: schema.TypeString, + Description: "Read-only timestamp marking the most recent intention update.", + Optional: true, + }, + }, + }, + }, + } +} + +func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { + configEntry := &consulapi.ServiceIntentionsConfigEntry{ + Kind: consulapi.ServiceIntentions, + Name: d.Get("name").(string), + Meta: map[string]string{}, + } + + if d.Get("namespace") != nil { + configEntry.Namespace = d.Get("namespace").(string) + } + + if d.Get("partition") != nil { + configEntry.Partition = d.Get("partition").(string) + } + + if d.Get("meta") != nil { + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) + } + } + + jwt := d.Get("jwt").(*schema.Set).List() + + if len(jwt) > 0 { + jwtMap := jwt[0].(map[string]interface{}) + var jwtReq *consulapi.IntentionJWTRequirement + jwtReq = new(consulapi.IntentionJWTRequirement) + providers := make([]*consulapi.IntentionJWTProvider, 0) + providerList := jwtMap["providers"].([]interface{}) + for _, pv := range providerList { + pvm := pv.(map[string]interface{}) + var provider *consulapi.IntentionJWTProvider + provider = new(consulapi.IntentionJWTProvider) + if pvm["name"] != nil { + provider.Name = pvm["name"].(string) + } + verifyClaims := make([]*consulapi.IntentionJWTClaimVerification, 0) + if pvm["verify_claims"] != nil { + verifyClaimsList := pvm["verify_claims"].([]interface{}) + for _, vcv := range verifyClaimsList { + vcMap := vcv.(map[string]interface{}) + var verifyClaim *consulapi.IntentionJWTClaimVerification + verifyClaim = new(consulapi.IntentionJWTClaimVerification) + verifyClaimPath := make([]string, 0) + for _, vcp := range vcMap["path"].([]interface{}) { + verifyClaimPath = append(verifyClaimPath, vcp.(string)) + } + verifyClaim.Path = verifyClaimPath + if vcMap["value"] != nil { + verifyClaim.Value = vcMap["value"].(string) + } + verifyClaims = append(verifyClaims, verifyClaim) + } + } + providerList = append(providerList, provider) + } + jwtReq.Providers = providers + configEntry.JWT = jwtReq + } + + sources := d.Get("sources") + sourcesList := sources.([]interface{}) + + if len(sourcesList) > 0 { + sourcesIntentions := make([]*consulapi.SourceIntention, 0) + for _, sr := range sourcesList { + var sourceIntention *consulapi.SourceIntention + sourceMap := sr.(map[string]interface{}) + if sourceMap["name"] != nil { + sourceIntention.Name = sourceMap["name"].(string) + } + if sourceMap["peer"] != nil { + sourceIntention.Peer = sourceMap["peer"].(string) + } + if sourceMap["namespace"] != nil { + sourceIntention.Namespace = sourceMap["namespace"].(string) + } + if sourceMap["partition"] != nil { + sourceIntention.Partition = sourceMap["partition"].(string) + } + if sourceMap["sameness_group"] != nil { + sourceIntention.SamenessGroup = sourceMap["sameness_group"].(string) + } + if sourceMap["action"] != nil { + if sourceMap["action"].(string) == "allow" { + sourceIntention.Action = consulapi.IntentionActionAllow + } else if sourceMap["action"].(string) == "deny" { + sourceIntention.Action = consulapi.IntentionActionDeny + } else { + return nil, fmt.Errorf("action is invalid. it should either be allow or deny") + } + } + if sourceMap["permissions"] != nil { + intentionPermissions := make([]*consulapi.IntentionPermission, 0) + permissionList := sourceMap["permissions"].([]interface{}) + for _, permission := range permissionList { + var intentionPermission *consulapi.IntentionPermission + intentionPermission = new(consulapi.IntentionPermission) + permissionMap := permission.(map[string]interface{}) + if permissionMap["action"] != nil && permissionMap["action"].(string) == "allow" { + intentionPermission.Action = consulapi.IntentionActionAllow + } else if permissionMap["action"] != nil && permissionMap["action"].(string) == "deny" { + intentionPermission.Action = consulapi.IntentionActionDeny + } else { + return nil, fmt.Errorf("action is invalid. it should either be allow or deny") + } + if permissionMap["http"] != nil { + var intentionPermissionHTTP *consulapi.IntentionHTTPPermission + intentionPermissionHTTP = new(consulapi.IntentionHTTPPermission) + httpMap := permissionMap["http"].(map[string]interface{}) + if httpMap["path_exact"] != nil { + intentionPermissionHTTP.PathExact = httpMap["path_exact"].(string) + } + if httpMap["path_prefix"] != nil { + intentionPermissionHTTP.PathPrefix = httpMap["path_prefix"].(string) + } + if httpMap["path_regex"] != nil { + intentionPermissionHTTP.PathPrefix = httpMap["path_regex"].(string) + } + if httpMap["methods"] != nil { + httpMethods := make([]string, 0) + for _, v := range httpMap["methods"].([]interface{}) { + httpMethods = append(httpMethods, v.(string)) + } + intentionPermissionHTTP.Methods = httpMethods + } + intentionPermission.HTTP = intentionPermissionHTTP + if httpMap["headers"] != nil { + httpHeaderPermissions := make([]consulapi.IntentionHTTPHeaderPermission, 0) + for _, v := range httpMap["headers"].([]interface{}) { + var httpHeaderPermission consulapi.IntentionHTTPHeaderPermission + headerPermissionMap := v.(map[string]interface{}) + if headerPermissionMap["name"] != nil { + httpHeaderPermission.Name = headerPermissionMap["name"].(string) + } + if headerPermissionMap["present"] != nil { + httpHeaderPermission.Present = headerPermissionMap["present"].(bool) + } + if headerPermissionMap["exact"] != nil { + httpHeaderPermission.Exact = headerPermissionMap["exact"].(string) + } + if headerPermissionMap["prefix"] != nil { + httpHeaderPermission.Prefix = headerPermissionMap["prefix"].(string) + } + if headerPermissionMap["suffix"] != nil { + httpHeaderPermission.Suffix = headerPermissionMap["suffix"].(string) + } + if headerPermissionMap["regex"] != nil { + httpHeaderPermission.Regex = headerPermissionMap["regex"].(string) + } + if headerPermissionMap["invert"] != nil { + httpHeaderPermission.Invert = headerPermissionMap["invert"].(bool) + } + httpHeaderPermissions = append(httpHeaderPermissions, httpHeaderPermission) + } + } + } + intentionPermissions = append(intentionPermissions, intentionPermission) + } + sourceIntention.Permissions = intentionPermissions + } + if sourceMap["precedence"] != nil { + sourceIntention.Precedence = sourceMap["precedence"].(int) + } + if sourceMap["type"] != nil { + typeSourceIntention := consulapi.IntentionSourceType(sourceMap["type"].(string)) + sourceIntention.Type = typeSourceIntention + } + if sourceMap["description"] != nil { + sourceIntention.Description = sourceMap["description"].(string) + } + if sourceMap["legacy_id"] != nil { + sourceIntention.LegacyID = sourceMap["legacy_id"].(string) + } + if sourceMap["legacy_meta"] != nil { + legacyMeta := make(map[string]string) + for k, v := range sourceMap["legacy_meta"].(map[string]string) { + legacyMeta[k] = v + } + sourceIntention.LegacyMeta = legacyMeta + } + if sourceMap["legacy_create_time"] != nil { + sourceIntention.LegacyID = sourceMap["legacy_create_time"].(string) + } + if sourceMap["legacy_update_time"] != nil { + sourceIntention.LegacyID = sourceMap["legacy_update_time"].(string) + } + sourcesIntentions = append(sourcesIntentions, sourceIntention) + } + configEntry.Sources = sourcesIntentions + } + + return configEntry, nil +} + +func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { + si, ok := ce.(*consulapi.ServiceIntentionsConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceRouter, ce.GetKind()) + } + + sw.set("name", si.Name) + sw.set("partition", si.Partition) + sw.set("namespace", si.Namespace) + + meta := map[string]interface{}{} + for k, v := range si.Meta { + meta[k] = v + } + sw.set("meta", meta) + + jwt := make([]map[string]interface{}, 1) + jwt[0] = make(map[string]interface{}) + jwt[0]["providers"] = make([]map[string]interface{}, 0) + jwtProviders := make([]map[string]interface{}, 0) + for _, jwtProvider := range si.JWT.Providers { + jwtProviderMap := make(map[string]interface{}) + jwtProviderMap["name"] = jwtProvider.Name + jwtProviderMap["verify_claims"] = make([]map[string]interface{}, 0) + verifyClaims := make([]map[string]interface{}, 0) + for _, vc := range jwtProvider.VerifyClaims { + vcMap := make(map[string]interface{}) + vcPaths := make([]string, 0) + for _, p := range vc.Path { + vcPaths = append(vcPaths, p) + } + vcMap["path"] = vcPaths + vcMap["value"] = vc.Value + verifyClaims = append(verifyClaims, vcMap) + } + jwtProviders = append(jwtProviders, jwtProviderMap) + } + jwt[0]["providers"] = jwtProviders + + sw.set("jwt", jwt) + + sources := make([]map[string]interface{}, 0) + for _, source := range si.Sources { + sourceMap := make(map[string]interface{}) + sourceMap["name"] = source.Name + sourceMap["peer"] = source.Peer + sourceMap["namespace"] = source.Namespace + sourceMap["partition"] = source.Partition + sourceMap["sameness_group"] = source.SamenessGroup + sourceMap["action"] = source.Action + sourceMap["precedence"] = source.Precedence + sourceMap["type"] = source.Type + sourceMap["description"] = source.Description + sourceMap["legacy_id"] = source.LegacyID + sourceMap["legacy_meta"] = source.LegacyMeta + sourceMap["legacy_create_time"] = source.LegacyCreateTime + sourceMap["legacy_update_time"] = source.LegacyUpdateTime + permissions := make([]map[string]interface{}, 0) + for _, permission := range source.Permissions { + permissionMap := make(map[string]interface{}) + permissionMap["action"] = permission.Action + permissionHttp := make([]map[string]interface{}, 0) + permissionHttp[0] = make(map[string]interface{}) + permissionHttp[0]["path_exact"] = permission.HTTP.PathExact + permissionHttp[0]["path_prefix"] = permission.HTTP.PathPrefix + permissionHttp[0]["path_regex"] = permission.HTTP.PathRegex + permissionHttp[0]["methods"] = permission.HTTP.Methods + headers := make([]map[string]interface{}, 0) + for _, header := range permission.HTTP.Header { + headerMap := make(map[string]interface{}) + headerMap["name"] = header.Name + headerMap["present"] = header.Present + headerMap["exact"] = header.Exact + headerMap["prefix"] = header.Prefix + headerMap["suffix"] = header.Suffix + headerMap["regex"] = header.Regex + headerMap["invert"] = header.Invert + headers = append(headers, headerMap) + } + permissionHttp[0]["headers"] = headers + permissionMap["http"] = permissionHttp + permissions = append(permissions, permissionMap) + } + sourceMap["permissions"] = permissions + } + + sw.set("sources", sources) + + return nil +} diff --git a/consul/resource_consul_config_entry_service_splitter.go b/consul/resource_consul_config_entry_service_splitter.go index aa958866..a953afe9 100644 --- a/consul/resource_consul_config_entry_service_splitter.go +++ b/consul/resource_consul_config_entry_service_splitter.go @@ -224,7 +224,7 @@ func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } sw.set("meta", meta) - splits := []interface{}{} + splits := make([]interface{}, 0) for _, s := range sp.Splits { split := map[string]interface{}{ "weight": s.Weight, diff --git a/consul/resource_provider.go b/consul/resource_provider.go index c32e164b..c31045f9 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -225,34 +225,35 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "consul_acl_auth_method": resourceConsulACLAuthMethod(), - "consul_acl_binding_rule": resourceConsulACLBindingRule(), - "consul_acl_policy": resourceConsulACLPolicy(), - "consul_acl_role": resourceConsulACLRole(), - "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), - "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), - "consul_acl_token": resourceConsulACLToken(), - "consul_admin_partition": resourceConsulAdminPartition(), - "consul_agent_service": resourceConsulAgentService(), - "consul_autopilot_config": resourceConsulAutopilotConfig(), - "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(), - "consul_keys": resourceConsulKeys(), - "consul_license": resourceConsulLicense(), - "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), - "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), - "consul_namespace": resourceConsulNamespace(), - "consul_network_area": resourceConsulNetworkArea(), - "consul_node": resourceConsulNode(), - "consul_peering_token": resourceSourceConsulPeeringToken(), - "consul_peering": resourceSourceConsulPeering(), - "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_service": resourceConsulService(), + "consul_acl_auth_method": resourceConsulACLAuthMethod(), + "consul_acl_binding_rule": resourceConsulACLBindingRule(), + "consul_acl_policy": resourceConsulACLPolicy(), + "consul_acl_role": resourceConsulACLRole(), + "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), + "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), + "consul_acl_token": resourceConsulACLToken(), + "consul_admin_partition": resourceConsulAdminPartition(), + "consul_agent_service": resourceConsulAgentService(), + "consul_autopilot_config": resourceConsulAutopilotConfig(), + "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_service_intentions": resourceFromConfigEntryImplementation(&serviceIntentions{}), + "consul_config_entry": resourceConsulConfigEntry(), + "consul_intention": resourceConsulIntention(), + "consul_key_prefix": resourceConsulKeyPrefix(), + "consul_keys": resourceConsulKeys(), + "consul_license": resourceConsulLicense(), + "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), + "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), + "consul_namespace": resourceConsulNamespace(), + "consul_network_area": resourceConsulNetworkArea(), + "consul_node": resourceConsulNode(), + "consul_peering_token": resourceSourceConsulPeeringToken(), + "consul_peering": resourceSourceConsulPeering(), + "consul_prepared_query": resourceConsulPreparedQuery(), + "consul_service": resourceConsulService(), }, ConfigureFunc: providerConfigure, From bee3491d906ca7dcc25124ba3074606f8204dc68 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 15:33:26 +0530 Subject: [PATCH 76/89] fix resource provider --- consul/resource_provider.go | 61 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/consul/resource_provider.go b/consul/resource_provider.go index d26d4536..bbb1b1c1 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -225,36 +225,37 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "consul_acl_auth_method": resourceConsulACLAuthMethod(), - "consul_acl_binding_rule": resourceConsulACLBindingRule(), - "consul_acl_policy": resourceConsulACLPolicy(), - "consul_acl_role": resourceConsulACLRole(), - "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), - "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), - "consul_acl_token": resourceConsulACLToken(), - "consul_admin_partition": resourceConsulAdminPartition(), - "consul_agent_service": resourceConsulAgentService(), - "consul_autopilot_config": resourceConsulAutopilotConfig(), - "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_service_router": resourceFromConfigEntryImplementation(&serviceRouter{}), - "consul_config_entry_service_resolver": resourceFromConfigEntryImplementation(&serviceResolver{}), - "consul_config_entry": resourceConsulConfigEntry(), - "consul_intention": resourceConsulIntention(), - "consul_key_prefix": resourceConsulKeyPrefix(), - "consul_keys": resourceConsulKeys(), - "consul_license": resourceConsulLicense(), - "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), - "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), - "consul_namespace": resourceConsulNamespace(), - "consul_network_area": resourceConsulNetworkArea(), - "consul_node": resourceConsulNode(), - "consul_peering_token": resourceSourceConsulPeeringToken(), - "consul_peering": resourceSourceConsulPeering(), - "consul_prepared_query": resourceConsulPreparedQuery(), - "consul_service": resourceConsulService(), + "consul_acl_auth_method": resourceConsulACLAuthMethod(), + "consul_acl_binding_rule": resourceConsulACLBindingRule(), + "consul_acl_policy": resourceConsulACLPolicy(), + "consul_acl_role": resourceConsulACLRole(), + "consul_acl_token_policy_attachment": resourceConsulACLTokenPolicyAttachment(), + "consul_acl_token_role_attachment": resourceConsulACLTokenRoleAttachment(), + "consul_acl_token": resourceConsulACLToken(), + "consul_admin_partition": resourceConsulAdminPartition(), + "consul_agent_service": resourceConsulAgentService(), + "consul_autopilot_config": resourceConsulAutopilotConfig(), + "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_service_router": resourceFromConfigEntryImplementation(&serviceRouter{}), + "consul_config_entry_service_resolver": resourceFromConfigEntryImplementation(&serviceResolver{}), + "consul_config_entry_service_intentions": resourceFromConfigEntryImplementation(&serviceIntentions{}), + "consul_config_entry": resourceConsulConfigEntry(), + "consul_intention": resourceConsulIntention(), + "consul_key_prefix": resourceConsulKeyPrefix(), + "consul_keys": resourceConsulKeys(), + "consul_license": resourceConsulLicense(), + "consul_namespace_policy_attachment": resourceConsulNamespacePolicyAttachment(), + "consul_namespace_role_attachment": resourceConsulNamespaceRoleAttachment(), + "consul_namespace": resourceConsulNamespace(), + "consul_network_area": resourceConsulNetworkArea(), + "consul_node": resourceConsulNode(), + "consul_peering_token": resourceSourceConsulPeeringToken(), + "consul_peering": resourceSourceConsulPeering(), + "consul_prepared_query": resourceConsulPreparedQuery(), + "consul_service": resourceConsulService(), }, ConfigureFunc: providerConfigure, From 56cc86266d91bb72ea4226e2d3b4ac7bc7721a98 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 16:28:09 +0530 Subject: [PATCH 77/89] fix intentinos schema --- consul/resource_consul_config_entry_service_intentions.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index b0f36370..a8e1210b 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -72,7 +72,7 @@ func (s *serviceIntentions) GetSchema() map[string]*schema.Schema { Type: schema.TypeList, Optional: true, Description: "Specifies the path to the claim in the JSON web token.", - Elem: schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{Type: schema.TypeString}, }, "value": { Type: schema.TypeString, @@ -160,11 +160,12 @@ func (s *serviceIntentions) GetSchema() map[string]*schema.Schema { Type: schema.TypeList, Description: "Specifies a list of HTTP methods.", Optional: true, - Elem: schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{Type: schema.TypeString}, }, "headers": { Type: schema.TypeList, Description: "Specifies a header name and matching criteria for HTTP request headers.", + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -221,6 +222,7 @@ func (s *serviceIntentions) GetSchema() map[string]*schema.Schema { Type: schema.TypeString, Default: "consul", Description: "Specifies the type of destination service that the configuration entry applies to.", + Optional: true, }, "description": { Type: schema.TypeString, @@ -236,7 +238,7 @@ func (s *serviceIntentions) GetSchema() map[string]*schema.Schema { Type: schema.TypeMap, Optional: true, Description: "Read-only set of arbitrary key-value pairs to attach to the intention.", - Elem: schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{Type: schema.TypeString}, }, "legacy_create_time": { Type: schema.TypeString, From 28bd93e915ac99a363fae94def5d5c29fce96133 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 17:20:58 +0530 Subject: [PATCH 78/89] fix intentions --- consul/resource_consul_config_entry_service_intentions.go | 8 +++++--- ...urce_consul_config_entry_service_intentions_ce_test.go | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index a8e1210b..68928d39 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -309,8 +309,9 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr } verifyClaims = append(verifyClaims, verifyClaim) } + provider.VerifyClaims = verifyClaims } - providerList = append(providerList, provider) + providers = append(providers, provider) } jwtReq.Providers = providers configEntry.JWT = jwtReq @@ -323,6 +324,7 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr sourcesIntentions := make([]*consulapi.SourceIntention, 0) for _, sr := range sourcesList { var sourceIntention *consulapi.SourceIntention + sourceIntention = new(consulapi.SourceIntention) sourceMap := sr.(map[string]interface{}) if sourceMap["name"] != nil { sourceIntention.Name = sourceMap["name"].(string) @@ -432,8 +434,8 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr } if sourceMap["legacy_meta"] != nil { legacyMeta := make(map[string]string) - for k, v := range sourceMap["legacy_meta"].(map[string]string) { - legacyMeta[k] = v + for k, v := range sourceMap["legacy_meta"].(map[string]interface{}) { + legacyMeta[k] = v.(string) } sourceIntention.LegacyMeta = legacyMeta } diff --git a/consul/resource_consul_config_entry_service_intentions_ce_test.go b/consul/resource_consul_config_entry_service_intentions_ce_test.go index 8917a012..ca1ee4d9 100644 --- a/consul/resource_consul_config_entry_service_intentions_ce_test.go +++ b/consul/resource_consul_config_entry_service_intentions_ce_test.go @@ -25,5 +25,5 @@ func TestAccConsulConfigEntryServiceIntentionsCETest(t *testing.T) { } const testConsulConfigEntryServiceIntentionsCE = ` - + resource ` From 5ac3ed7f6f953903e58e4b69b69dbd1fc202504f Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 17:30:49 +0530 Subject: [PATCH 79/89] intentions fixes --- ..._consul_config_entry_service_intentions.go | 91 ++++++++++--------- ...config_entry_service_intentions_ce_test.go | 31 ++++++- 2 files changed, 76 insertions(+), 46 deletions(-) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index 68928d39..9facc3dc 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -346,8 +346,6 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr sourceIntention.Action = consulapi.IntentionActionAllow } else if sourceMap["action"].(string) == "deny" { sourceIntention.Action = consulapi.IntentionActionDeny - } else { - return nil, fmt.Errorf("action is invalid. it should either be allow or deny") } } if sourceMap["permissions"] != nil { @@ -367,51 +365,54 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr if permissionMap["http"] != nil { var intentionPermissionHTTP *consulapi.IntentionHTTPPermission intentionPermissionHTTP = new(consulapi.IntentionHTTPPermission) - httpMap := permissionMap["http"].(map[string]interface{}) - if httpMap["path_exact"] != nil { - intentionPermissionHTTP.PathExact = httpMap["path_exact"].(string) - } - if httpMap["path_prefix"] != nil { - intentionPermissionHTTP.PathPrefix = httpMap["path_prefix"].(string) - } - if httpMap["path_regex"] != nil { - intentionPermissionHTTP.PathPrefix = httpMap["path_regex"].(string) - } - if httpMap["methods"] != nil { - httpMethods := make([]string, 0) - for _, v := range httpMap["methods"].([]interface{}) { - httpMethods = append(httpMethods, v.(string)) + httpMap := permissionMap["http"].(*schema.Set).List() + if len(httpMap) > 0 { + httpMapFirst := httpMap[0].(map[string]interface{}) + if httpMapFirst["path_exact"] != nil { + intentionPermissionHTTP.PathExact = httpMapFirst["path_exact"].(string) } - intentionPermissionHTTP.Methods = httpMethods - } - intentionPermission.HTTP = intentionPermissionHTTP - if httpMap["headers"] != nil { - httpHeaderPermissions := make([]consulapi.IntentionHTTPHeaderPermission, 0) - for _, v := range httpMap["headers"].([]interface{}) { - var httpHeaderPermission consulapi.IntentionHTTPHeaderPermission - headerPermissionMap := v.(map[string]interface{}) - if headerPermissionMap["name"] != nil { - httpHeaderPermission.Name = headerPermissionMap["name"].(string) - } - if headerPermissionMap["present"] != nil { - httpHeaderPermission.Present = headerPermissionMap["present"].(bool) - } - if headerPermissionMap["exact"] != nil { - httpHeaderPermission.Exact = headerPermissionMap["exact"].(string) - } - if headerPermissionMap["prefix"] != nil { - httpHeaderPermission.Prefix = headerPermissionMap["prefix"].(string) - } - if headerPermissionMap["suffix"] != nil { - httpHeaderPermission.Suffix = headerPermissionMap["suffix"].(string) - } - if headerPermissionMap["regex"] != nil { - httpHeaderPermission.Regex = headerPermissionMap["regex"].(string) + if httpMapFirst["path_prefix"] != nil { + intentionPermissionHTTP.PathPrefix = httpMapFirst["path_prefix"].(string) + } + if httpMapFirst["path_regex"] != nil { + intentionPermissionHTTP.PathPrefix = httpMapFirst["path_regex"].(string) + } + if httpMapFirst["methods"] != nil { + httpMethods := make([]string, 0) + for _, v := range httpMapFirst["methods"].([]interface{}) { + httpMethods = append(httpMethods, v.(string)) } - if headerPermissionMap["invert"] != nil { - httpHeaderPermission.Invert = headerPermissionMap["invert"].(bool) + intentionPermissionHTTP.Methods = httpMethods + } + intentionPermission.HTTP = intentionPermissionHTTP + if httpMapFirst["headers"] != nil { + httpHeaderPermissions := make([]consulapi.IntentionHTTPHeaderPermission, 0) + for _, v := range httpMapFirst["headers"].([]interface{}) { + var httpHeaderPermission consulapi.IntentionHTTPHeaderPermission + headerPermissionMap := v.(map[string]interface{}) + if headerPermissionMap["name"] != nil { + httpHeaderPermission.Name = headerPermissionMap["name"].(string) + } + if headerPermissionMap["present"] != nil { + httpHeaderPermission.Present = headerPermissionMap["present"].(bool) + } + if headerPermissionMap["exact"] != nil { + httpHeaderPermission.Exact = headerPermissionMap["exact"].(string) + } + if headerPermissionMap["prefix"] != nil { + httpHeaderPermission.Prefix = headerPermissionMap["prefix"].(string) + } + if headerPermissionMap["suffix"] != nil { + httpHeaderPermission.Suffix = headerPermissionMap["suffix"].(string) + } + if headerPermissionMap["regex"] != nil { + httpHeaderPermission.Regex = headerPermissionMap["regex"].(string) + } + if headerPermissionMap["invert"] != nil { + httpHeaderPermission.Invert = headerPermissionMap["invert"].(bool) + } + httpHeaderPermissions = append(httpHeaderPermissions, httpHeaderPermission) } - httpHeaderPermissions = append(httpHeaderPermissions, httpHeaderPermission) } } } @@ -514,7 +515,7 @@ func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, sw *stateWriter) err for _, permission := range source.Permissions { permissionMap := make(map[string]interface{}) permissionMap["action"] = permission.Action - permissionHttp := make([]map[string]interface{}, 0) + permissionHttp := make([]map[string]interface{}, 1) permissionHttp[0] = make(map[string]interface{}) permissionHttp[0]["path_exact"] = permission.HTTP.PathExact permissionHttp[0]["path_prefix"] = permission.HTTP.PathPrefix diff --git a/consul/resource_consul_config_entry_service_intentions_ce_test.go b/consul/resource_consul_config_entry_service_intentions_ce_test.go index ca1ee4d9..88fb6b11 100644 --- a/consul/resource_consul_config_entry_service_intentions_ce_test.go +++ b/consul/resource_consul_config_entry_service_intentions_ce_test.go @@ -25,5 +25,34 @@ func TestAccConsulConfigEntryServiceIntentionsCETest(t *testing.T) { } const testConsulConfigEntryServiceIntentionsCE = ` - resource + + name = "service-intention-3" + meta = { + key = "value" + } + jwt { + providers { + name = consul_config_entry.jwt_provider.name + verify_claims { + path = ["/", "path1"] + value = "" + } + verify_claims { + path = ["/path"] + value = "value" + } + } + } + sources { + action = "allow" + name = "frontend-webapp" + precedence = 9 + type = "consul" + } + sources { + action = "allow" + name = "nightly-cronjob" + precedence = 9 + type = "consul" + } ` From 31aec221f43ccc5119684b8a863770fc19dab7f5 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 4 Oct 2023 17:34:23 +0530 Subject: [PATCH 80/89] intentions test --- ...config_entry_service_intentions_ce_test.go | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/consul/resource_consul_config_entry_service_intentions_ce_test.go b/consul/resource_consul_config_entry_service_intentions_ce_test.go index 88fb6b11..a8cb33c6 100644 --- a/consul/resource_consul_config_entry_service_intentions_ce_test.go +++ b/consul/resource_consul_config_entry_service_intentions_ce_test.go @@ -18,15 +18,31 @@ func TestAccConsulConfigEntryServiceIntentionsCETest(t *testing.T) { Steps: []resource.TestStep{ { Config: testConsulConfigEntryServiceIntentionsCE, - Check: resource.ComposeTestCheckFunc(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "name", "service-intention"), + ), }, }, }) } const testConsulConfigEntryServiceIntentionsCE = ` +resource "consul_config_entry" "jwt_provider" { + name = "okta" + kind = "jwt-provider" - name = "service-intention-3" + config_json = jsonencode({ + Issuer = "test-issuer" + JSONWebKeySet = { + Remote = { + URI = "https://127.0.0.1:9091" + FetchAsynchronously = true + } + } + }) +} +resource "consul_config_entry_service_intentions" "foo" { + name = "service-intention" meta = { key = "value" } @@ -50,9 +66,10 @@ const testConsulConfigEntryServiceIntentionsCE = ` type = "consul" } sources { - action = "allow" name = "nightly-cronjob" precedence = 9 type = "consul" + action = "deny" } +} ` From 3b703a94a29a1a513ee1ffb8c3c23fb7ec3b3539 Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 11:25:19 -0700 Subject: [PATCH 81/89] [COMPLIANCE] Add Copyright and License Headers (#353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Rémi Lapeyre --- .copywrite.hcl | 20 ++++++++++++++++++++ LICENSE | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .copywrite.hcl diff --git a/.copywrite.hcl b/.copywrite.hcl new file mode 100644 index 00000000..07f43e75 --- /dev/null +++ b/.copywrite.hcl @@ -0,0 +1,20 @@ +schema_version = 1 + +project { + license = "MPL-2.0" + copyright_year = 2023 + + header_ignore = [ + # examples used within documentation (prose) + "examples/**", + + # GitHub issue template configuration + ".github/ISSUE_TEMPLATE/*.yml", + + # golangci-lint tooling configuration + ".golangci.yml", + + # GoReleaser tooling configuration + ".goreleaser.yml", + ] +} diff --git a/LICENSE b/LICENSE index b9ac071e..0efb0a53 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017 HashiCorp, Inc. +Copyright (c) 2023 HashiCorp, Inc. Mozilla Public License Version 2.0 ================================== From bb9bac09e4f183d0130f04ef6cb766e0184f57d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Sun, 8 Oct 2023 12:26:24 -0700 Subject: [PATCH 82/89] Fix consul_service resource documentation (#352) Closes https://github.com/hashicorp/terraform-provider-consul/issues/350 --- .github/workflows/test.yaml | 23 +++- consul/resource_consul_service.go | 157 +++++++++++++++++----------- docs/resources/service.md | 117 +++++++++------------ go.mod | 2 +- go.sum | 8 ++ templates/resources/service.md | 154 --------------------------- templates/resources/service.md.tmpl | 73 +++++++++++++ 7 files changed, 249 insertions(+), 285 deletions(-) delete mode 100644 templates/resources/service.md create mode 100644 templates/resources/service.md.tmpl diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 75490490..88f03496 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.19.x, 1.20.x] + go-version: [1.20.x, 1.21.x] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: @@ -24,8 +24,25 @@ jobs: run: make test - name: Run OSS acceptance tests run: | - curl -LO https://releases.hashicorp.com/consul/1.16.0/consul_1.16.0_linux_amd64.zip - sudo unzip consul_1.16.0_linux_amd64.zip consul -d /usr/local/bin + curl -LO https://releases.hashicorp.com/consul/1.16.2/consul_1.16.2_linux_amd64.zip + sudo unzip consul_1.16.2_linux_amd64.zip consul -d /usr/local/bin SKIP_REMOTE_DATACENTER_TESTS=1 make testacc TESTARGS="-count=1" - name: Run go vet run: make vet + + docs: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + with: + go-version: 1.20.x + - name: Checkout code + uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - name: Run OSS acceptance tests + run: | + curl -LO https://github.com/hashicorp/terraform-plugin-docs/releases/download/v0.16.0/tfplugindocs_0.16.0_linux_amd64.zip + sudo unzip tfplugindocs_0.16.0_linux_amd64.zip tfplugindocs -d /usr/local/bin + tfplugindocs generate --ignore-deprecated true + - name: Fail if repo has changes + uses: UnicornGlobal/has-changes-action@ea00e6f831a9e785271645729fa251907b314707 # v1.0.12 diff --git a/consul/resource_consul_service.go b/consul/resource_consul_service.go index 269e2002..628137f3 100644 --- a/consul/resource_consul_service.go +++ b/consul/resource_consul_service.go @@ -17,13 +17,15 @@ import ( var headerResource = &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Description: "The name of the header.", }, "value": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "The header's list of values.", }, }, } @@ -45,37 +47,53 @@ func resourceConsulService() *schema.Resource { Read: resourceConsulServiceRead, Delete: resourceConsulServiceDelete, + Description: ` +A high-level resource for creating a Service in Consul in the Consul catalog. This +is appropriate for registering [external services](https://www.consul.io/docs/guides/external.html) and +can be used to create services addressable by Consul that cannot be registered +with a [local agent](https://www.consul.io/docs/agent/basics.html). + +-> **NOTE:** If a Consul agent is running on the node where this service is +registered, it is not recommended to use this resource as the service will be +removed during the next [anti-entropy synchronization](https://www.consul.io/docs/architecture/anti-entropy). +`, + Schema: map[string]*schema.Schema{ "address": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The address of the service. Defaults to the address of the node.", }, "service_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "If the service ID is not provided, it will be defaulted to the value of the `name` attribute.", }, "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the service.", }, "node": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the node the to register the service on.", }, "datacenter": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The datacenter to use. This overrides the agent's default datacenter and the datacenter in the provider setup.", }, "external": { @@ -85,14 +103,16 @@ func resourceConsulService() *schema.Resource { }, "port": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + Description: "The port of the service.", }, "tags": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "A list of values that are opaque to Consul, but can be used to distinguish between services or nodes.", }, "meta": { @@ -101,6 +121,7 @@ func resourceConsulService() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + Description: "A map of arbitrary KV metadata linked to the service instance.", }, "check": { @@ -137,76 +158,89 @@ func resourceConsulService() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "check_id": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Description: "An ID, *unique per agent*.", }, "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Description: "The name of the health-check.", }, "notes": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "An opaque field meant to hold human readable text.", }, "status": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The initial health-check status.", }, "tcp": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "The TCP address and port to connect to for a TCP check.", }, "http": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "The HTTP endpoint to call for an HTTP check.", }, "header": { - Type: schema.TypeSet, - Optional: true, - Elem: headerResource, + Type: schema.TypeSet, + Optional: true, + Elem: headerResource, + Description: "The headers to send for an HTTP check. The attributes of each header is given below.", }, "tls_skip_verify": { - Type: schema.TypeBool, - Optional: true, - Default: false, + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to deactivate certificate verification for HTTP health-checks. Defaults to `false`.", }, "method": { - Type: schema.TypeString, - Optional: true, - Default: "GET", + Type: schema.TypeString, + Optional: true, + Default: "GET", + Description: "The method to use for HTTP health-checks. Defaults to `GET`.", }, "interval": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Description: "The interval to wait between each health-check invocation.", }, "timeout": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Description: "Specifies a timeout for outgoing connections in the case of a HTTP or TCP check.", }, "deregister_critical_service_after": { - Type: schema.TypeString, - Optional: true, - Default: "30s", + Type: schema.TypeString, + Optional: true, + Default: "30s", + Description: "The time after which the service is automatically deregistered when in the `critical` state. Defaults to `30s`.", }, }, }, }, "namespace": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The namespace to create the service within.", }, "partition": { @@ -217,8 +251,9 @@ func resourceConsulService() *schema.Resource { }, "enable_tag_override": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Description: "Specifies to disable the anti-entropy feature for this service's tags. Defaults to `false`.", }, }, } diff --git a/docs/resources/service.md b/docs/resources/service.md index 55081c16..87cacd7a 100644 --- a/docs/resources/service.md +++ b/docs/resources/service.md @@ -1,12 +1,17 @@ --- -layout: "consul" -page_title: "Consul: consul_service" -sidebar_current: "docs-consul-resource-service" +page_title: "consul_service Resource - terraform-provider-consul" +subcategory: "" description: |- - A high-level resource for creating a Service in Consul in the Consul catalog. + A high-level resource for creating a Service in Consul in the Consul catalog. This + is appropriate for registering external services https://www.consul.io/docs/guides/external.html and + can be used to create services addressable by Consul that cannot be registered + with a local agent https://www.consul.io/docs/agent/basics.html. + -> NOTE: If a Consul agent is running on the node where this service is + registered, it is not recommended to use this resource as the service will be + removed during the next anti-entropy synchronization https://www.consul.io/docs/architecture/anti-entropy. --- -# consul_service +# consul_service (Resource) A high-level resource for creating a Service in Consul in the Consul catalog. This is appropriate for registering [external services](https://www.consul.io/docs/guides/external.html) and @@ -17,6 +22,7 @@ with a [local agent](https://www.consul.io/docs/agent/basics.html). registered, it is not recommended to use this resource as the service will be removed during the next [anti-entropy synchronization](https://www.consul.io/docs/architecture/anti-entropy). + ## Example Usage Creating a new node with the service: @@ -77,78 +83,57 @@ resource "consul_service" "redis" { } ``` -## Argument Reference - -The following arguments are supported: - -* `name` - (Required, string) The name of the service. - -* `node` - (Required, string) The name of the node the to register the service on. - -* `address` - (Optional, string) The address of the service. Defaults to the - address of the node. - -* `service_id` (Optional, string) - If the service ID is not provided, it will be defaulted to the value -of the `name` attribute. + +## Schema -* `port` - (Optional, int) The port of the service. +### Required -* `checks` - (Optional, list of checks) Health-checks to register to monitor the - service. The list of attributes for each health-check is detailed below. +- `name` (String) The name of the service. +- `node` (String) The name of the node the to register the service on. -* `tags` - (Optional, set of strings) A list of values that are opaque to Consul, - but can be used to distinguish between services or nodes. +### Optional -* `enable_tag_override` - (Optional, boolean) Specifies to disable the - anti-entropy feature for this service's tags. Defaults to `false`. +- `address` (String) The address of the service. Defaults to the address of the node. +- `check` (Block Set) (see [below for nested schema](#nestedblock--check)) +- `datacenter` (String) The datacenter to use. This overrides the agent's default datacenter and the datacenter in the provider setup. +- `enable_tag_override` (Boolean) Specifies to disable the anti-entropy feature for this service's tags. Defaults to `false`. +- `external` (Boolean, Deprecated) +- `meta` (Map of String) A map of arbitrary KV metadata linked to the service instance. +- `namespace` (String) The namespace to create the service within. +- `partition` (String) The partition the service is associated with. +- `port` (Number) The port of the service. +- `service_id` (String) If the service ID is not provided, it will be defaulted to the value of the `name` attribute. +- `tags` (List of String) A list of values that are opaque to Consul, but can be used to distinguish between services or nodes. -* `datacenter` - (Optional) The datacenter to use. This overrides the - agent's default datacenter and the datacenter in the provider setup. +### Read-Only -* `meta` - (Optional) A map of arbitrary KV metadata linked to the service - instance. +- `id` (String) The ID of this resource. -* `namespace` - (Optional, Enterprise Only) The namespace to create the service within. + +### Nested Schema for `check` -* `partition` - (Optional, Enterprise Only) The partition the service is associated with. +Required: -The following attributes are available for each health-check: +- `check_id` (String) An ID, *unique per agent*. +- `interval` (String) The interval to wait between each health-check invocation. +- `name` (String) The name of the health-check. +- `timeout` (String) Specifies a timeout for outgoing connections in the case of a HTTP or TCP check. -* `check_id` - (Optional, string) An ID, *unique per agent*. Will default to *name* - if not set. -* `name` - (Required) The name of the health-check. -* `notes` - (Optional, string) An opaque field meant to hold human readable text. -* `status` - (Optional, string) The initial health-check status. -* `tcp` - (Optional, string) The TCP address and port to connect to for a TCP check. -* `http` - (Optional, string) The HTTP endpoint to call for an HTTP check. -* `header` - (Optional, set of headers) The headers to send for an HTTP check. - The attributes of each header is given below. -* `tls_skip_verify` - (Optional, boolean) Whether to deactivate certificate - verification for HTTP health-checks. Defaults to `false`. -* `method` - (Optional, string) The method to use for HTTP health-checks. Defaults - to `GET`. -* `interval` - (Required, string) The interval to wait between each health-check - invocation. -* `timeout` - (Required, string) Specifies a timeout for outgoing connections in - the case of a HTTP or TCP check. -* `deregister_critical_service_after` - (Optional, string) The time after which - the service is automatically deregistered when in the `critical` state. - Defaults to `30s`. +Optional: -Each `header` must have the following attributes: -* `name` - (Required, string) The name of the header. -* `value` - (Required, list of strings) The header's list of values. +- `deregister_critical_service_after` (String) The time after which the service is automatically deregistered when in the `critical` state. Defaults to `30s`. +- `header` (Block Set) The headers to send for an HTTP check. The attributes of each header is given below. (see [below for nested schema](#nestedblock--check--header)) +- `http` (String) The HTTP endpoint to call for an HTTP check. +- `method` (String) The method to use for HTTP health-checks. Defaults to `GET`. +- `notes` (String) An opaque field meant to hold human readable text. +- `status` (String) The initial health-check status. +- `tcp` (String) The TCP address and port to connect to for a TCP check. +- `tls_skip_verify` (Boolean) Whether to deactivate certificate verification for HTTP health-checks. Defaults to `false`. -## Attributes Reference + +### Nested Schema for `check.header` -The following attributes are exported: +Required: -* `service_id` - The ID of the service. -* `address` - The address of the service. -* `node` - The node the service is registered on. -* `name` - The name of the service. -* `port` - The port of the service. -* `tags` - The tags of the service. -* `checks` - The list of health-checks associated with the service. -* `datacenter` - The datacenter of the service. -* `meta` - A map of arbitrary KV metadata linked to the service instance. +- `name` (String) The name of the header. +- `value` (List of String) The header's list of values. diff --git a/go.mod b/go.mod index df391ba3..b48e012d 100644 --- a/go.mod +++ b/go.mod @@ -100,4 +100,4 @@ require ( google.golang.org/protobuf v1.29.1 // indirect ) -go 1.19 +go 1.21 diff --git a/go.sum b/go.sum index f704096c..6becda55 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,7 @@ cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQn cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -347,6 +348,7 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -370,6 +372,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -431,6 +434,7 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -444,6 +448,7 @@ github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhE github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -601,6 +606,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= @@ -621,6 +627,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -652,6 +659,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= diff --git a/templates/resources/service.md b/templates/resources/service.md deleted file mode 100644 index 55081c16..00000000 --- a/templates/resources/service.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -layout: "consul" -page_title: "Consul: consul_service" -sidebar_current: "docs-consul-resource-service" -description: |- - A high-level resource for creating a Service in Consul in the Consul catalog. ---- - -# consul_service - -A high-level resource for creating a Service in Consul in the Consul catalog. This -is appropriate for registering [external services](https://www.consul.io/docs/guides/external.html) and -can be used to create services addressable by Consul that cannot be registered -with a [local agent](https://www.consul.io/docs/agent/basics.html). - --> **NOTE:** If a Consul agent is running on the node where this service is -registered, it is not recommended to use this resource as the service will be -removed during the next [anti-entropy synchronization](https://www.consul.io/docs/architecture/anti-entropy). - -## Example Usage - -Creating a new node with the service: - -```hcl -resource "consul_service" "google" { - name = "google" - node = "${consul_node.compute.name}" - port = 80 - tags = ["tag0"] -} - -resource "consul_node" "compute" { - name = "compute-google" - address = "www.google.com" -} -``` - -Utilizing an existing known node: - -```hcl -resource "consul_service" "google" { - name = "google" - node = "google" - port = 443 -} -``` - -Register a health-check: - -```hcl -resource "consul_service" "redis" { - name = "redis" - node = "redis" - port = 6379 - - check { - check_id = "service:redis1" - name = "Redis health check" - status = "passing" - http = "https://www.hashicorptest.com" - tls_skip_verify = false - method = "PUT" - interval = "5s" - timeout = "1s" - deregister_critical_service_after = "30s" - - header { - name = "foo" - value = ["test"] - } - - header { - name = "bar" - value = ["test"] - } - } -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required, string) The name of the service. - -* `node` - (Required, string) The name of the node the to register the service on. - -* `address` - (Optional, string) The address of the service. Defaults to the - address of the node. - -* `service_id` (Optional, string) - If the service ID is not provided, it will be defaulted to the value -of the `name` attribute. - -* `port` - (Optional, int) The port of the service. - -* `checks` - (Optional, list of checks) Health-checks to register to monitor the - service. The list of attributes for each health-check is detailed below. - -* `tags` - (Optional, set of strings) A list of values that are opaque to Consul, - but can be used to distinguish between services or nodes. - -* `enable_tag_override` - (Optional, boolean) Specifies to disable the - anti-entropy feature for this service's tags. Defaults to `false`. - -* `datacenter` - (Optional) The datacenter to use. This overrides the - agent's default datacenter and the datacenter in the provider setup. - -* `meta` - (Optional) A map of arbitrary KV metadata linked to the service - instance. - -* `namespace` - (Optional, Enterprise Only) The namespace to create the service within. - -* `partition` - (Optional, Enterprise Only) The partition the service is associated with. - -The following attributes are available for each health-check: - -* `check_id` - (Optional, string) An ID, *unique per agent*. Will default to *name* - if not set. -* `name` - (Required) The name of the health-check. -* `notes` - (Optional, string) An opaque field meant to hold human readable text. -* `status` - (Optional, string) The initial health-check status. -* `tcp` - (Optional, string) The TCP address and port to connect to for a TCP check. -* `http` - (Optional, string) The HTTP endpoint to call for an HTTP check. -* `header` - (Optional, set of headers) The headers to send for an HTTP check. - The attributes of each header is given below. -* `tls_skip_verify` - (Optional, boolean) Whether to deactivate certificate - verification for HTTP health-checks. Defaults to `false`. -* `method` - (Optional, string) The method to use for HTTP health-checks. Defaults - to `GET`. -* `interval` - (Required, string) The interval to wait between each health-check - invocation. -* `timeout` - (Required, string) Specifies a timeout for outgoing connections in - the case of a HTTP or TCP check. -* `deregister_critical_service_after` - (Optional, string) The time after which - the service is automatically deregistered when in the `critical` state. - Defaults to `30s`. - -Each `header` must have the following attributes: -* `name` - (Required, string) The name of the header. -* `value` - (Required, list of strings) The header's list of values. - -## Attributes Reference - -The following attributes are exported: - -* `service_id` - The ID of the service. -* `address` - The address of the service. -* `node` - The node the service is registered on. -* `name` - The name of the service. -* `port` - The port of the service. -* `tags` - The tags of the service. -* `checks` - The list of health-checks associated with the service. -* `datacenter` - The datacenter of the service. -* `meta` - A map of arbitrary KV metadata linked to the service instance. diff --git a/templates/resources/service.md.tmpl b/templates/resources/service.md.tmpl new file mode 100644 index 00000000..949e626f --- /dev/null +++ b/templates/resources/service.md.tmpl @@ -0,0 +1,73 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + + +## Example Usage + +Creating a new node with the service: + +```hcl +resource "consul_service" "google" { + name = "google" + node = "${consul_node.compute.name}" + port = 80 + tags = ["tag0"] +} + +resource "consul_node" "compute" { + name = "compute-google" + address = "www.google.com" +} +``` + +Utilizing an existing known node: + +```hcl +resource "consul_service" "google" { + name = "google" + node = "google" + port = 443 +} +``` + +Register a health-check: + +```hcl +resource "consul_service" "redis" { + name = "redis" + node = "redis" + port = 6379 + + check { + check_id = "service:redis1" + name = "Redis health check" + status = "passing" + http = "https://www.hashicorptest.com" + tls_skip_verify = false + method = "PUT" + interval = "5s" + timeout = "1s" + deregister_critical_service_after = "30s" + + header { + name = "foo" + value = ["test"] + } + + header { + name = "bar" + value = ["test"] + } + } +} +``` + +{{ .SchemaMarkdown | trimspace }} From 656eb654c6a3118f0c709de080c8806c1b4a99b0 Mon Sep 17 00:00:00 2001 From: am-ak <114914687+am-ak@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:01:21 +0200 Subject: [PATCH 83/89] Indicate that max_token_ttl is required for OIDC auth methods (#360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémi Lapeyre --- .github/workflows/test.yaml | 12 +- consul/resource_consul_acl_auth_method.go | 28 ++-- docs/data-sources/config_entry.md | 2 - docs/data-sources/peering.md | 2 - docs/data-sources/peerings.md | 2 - docs/resources/acl_auth_method.md | 135 +++++++++--------- docs/resources/peering.md | 2 - docs/resources/peering_token.md | 2 - .../resources/consul_acl_auth_method/jwt.tf | 25 ++++ .../consul_acl_auth_method/kubernetes.tf | 11 ++ templates/resources/acl_auth_method.md | 98 ------------- templates/resources/acl_auth_method.md.tmpl | 32 +++++ 12 files changed, 160 insertions(+), 191 deletions(-) create mode 100644 examples/resources/consul_acl_auth_method/jwt.tf create mode 100644 examples/resources/consul_acl_auth_method/kubernetes.tf delete mode 100644 templates/resources/acl_auth_method.md create mode 100644 templates/resources/acl_auth_method.md.tmpl diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 88f03496..fbf1bad9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -39,10 +39,14 @@ jobs: go-version: 1.20.x - name: Checkout code uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - name: Run OSS acceptance tests + - name: Install tfplugindocs run: | curl -LO https://github.com/hashicorp/terraform-plugin-docs/releases/download/v0.16.0/tfplugindocs_0.16.0_linux_amd64.zip sudo unzip tfplugindocs_0.16.0_linux_amd64.zip tfplugindocs -d /usr/local/bin - tfplugindocs generate --ignore-deprecated true - - name: Fail if repo has changes - uses: UnicornGlobal/has-changes-action@ea00e6f831a9e785271645729fa251907b314707 # v1.0.12 + rm -f tfplugindocs_0.16.0_linux_amd64.zip + - name: Generate the documentation + run: tfplugindocs generate --ignore-deprecated true + - name: Fail if repository has changes + run: | + git status --short + [[ -z $(git status --porcelain) ]] || (echo "The docs/ folder is not up-to-date, please use 'tfplugindocs generate --ignore-deprecated true' to update it" && false) diff --git a/consul/resource_consul_acl_auth_method.go b/consul/resource_consul_acl_auth_method.go index 04b2a364..2bfbbbad 100644 --- a/consul/resource_consul_acl_auth_method.go +++ b/consul/resource_consul_acl_auth_method.go @@ -19,6 +19,8 @@ func resourceConsulACLAuthMethod() *schema.Resource { Update: resourceConsulACLAuthMethodUpdate, Delete: resourceConsulACLAuthMethodDelete, + Description: "Starting with Consul 1.5.0, the `consul_acl_auth_method` resource can be used to managed [Consul ACL auth methods](https://www.consul.io/docs/acl/auth-methods).", + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -44,7 +46,7 @@ func resourceConsulACLAuthMethod() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "0s", - Description: "The maximum life of any token created by this auth method.", + Description: "The maximum life of any token created by this auth method. **This attribute is required and must be set to a nonzero for the OIDC auth method.**", DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { o, err := time.ParseDuration(old) if err != nil { @@ -74,7 +76,7 @@ func resourceConsulACLAuthMethod() *schema.Resource { Type: schema.TypeMap, Optional: true, Description: "The raw configuration for this ACL auth method.", - Deprecated: "The config attribute is deprecated, please use config_json instead.", + Deprecated: "The config attribute is deprecated, please use `config_json` instead.", Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -95,26 +97,30 @@ func resourceConsulACLAuthMethod() *schema.Resource { }, "namespace_rule": { - Type: schema.TypeList, - Optional: true, + Type: schema.TypeList, + Description: "A set of rules that control which namespace tokens created via this auth method will be created within.", + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "selector": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Description: "Specifies the expression used to match this namespace rule against valid identities returned from an auth method validation.", + Optional: true, }, "bind_namespace": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Description: "If the namespace rule's `selector` matches then this is used to control the namespace where the token is created.", + Required: true, }, }, }, }, "namespace": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Description: "The namespace in which to create the auth method.", + Optional: true, + ForceNew: true, }, "partition": { diff --git a/docs/data-sources/config_entry.md b/docs/data-sources/config_entry.md index 2201c55e..1d9795bc 100644 --- a/docs/data-sources/config_entry.md +++ b/docs/data-sources/config_entry.md @@ -29,5 +29,3 @@ description: |- - `config_json` (String) The configuration of the config entry. - `id` (String) The ID of this resource. - - diff --git a/docs/data-sources/peering.md b/docs/data-sources/peering.md index 81ae332d..9c6152a8 100644 --- a/docs/data-sources/peering.md +++ b/docs/data-sources/peering.md @@ -39,5 +39,3 @@ data "consul_peering" "basic" { - `peer_server_addresses` (List of String) - `peer_server_name` (String) - `state` (String) - - diff --git a/docs/data-sources/peerings.md b/docs/data-sources/peerings.md index b578b1f7..8f71ecbd 100644 --- a/docs/data-sources/peerings.md +++ b/docs/data-sources/peerings.md @@ -43,5 +43,3 @@ Read-Only: - `peer_server_addresses` (List of String) - `peer_server_name` (String) - `state` (String) - - diff --git a/docs/resources/acl_auth_method.md b/docs/resources/acl_auth_method.md index 455ec38f..bdf6d58d 100644 --- a/docs/resources/acl_auth_method.md +++ b/docs/resources/acl_auth_method.md @@ -1,21 +1,19 @@ --- -layout: "consul" -page_title: "Consul: consul_acl_auth_method" -sidebar_current: "docs-consul-resource-acl-auth-method" +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_acl_auth_method Resource - terraform-provider-consul" description: |- - Allows Terraform to create an ACL auth method + Starting with Consul 1.5.0, the consul_acl_auth_method resource can be used to managed Consul ACL auth methods https://www.consul.io/docs/acl/auth-methods. --- -# consul_acl_auth_method - -Starting with Consul 1.5.0, the consul_acl_auth_method resource can be used to -managed [Consul ACL auth methods](https://www.consul.io/docs/acl/auth-methods). +# consul_acl_auth_method (Resource) +Starting with Consul 1.5.0, the `consul_acl_auth_method` resource can be used to managed [Consul ACL auth methods](https://www.consul.io/docs/acl/auth-methods). ## Example Usage Define a `kubernetes` auth method: -```hcl + +```terraform resource "consul_acl_auth_method" "minikube" { name = "minikube" type = "kubernetes" @@ -29,70 +27,71 @@ resource "consul_acl_auth_method" "minikube" { } ``` + Define a `jwt` auth method: -```hcl -resource "consul_acl_auth_method" "minikube" { - name = "auth_method" - type = "jwt" + +```terraform +resource "consul_acl_auth_method" "oidc" { + name = "auth0" + type = "oidc" + max_token_ttl = "5m" config_json = jsonencode({ - JWKSURL = "https://example.com/identity/oidc/.well-known/keys" - JWTSupportedAlgs = "RS256" - BoundIssuer = "https://example.com" - ClaimMappings = { - subject = "subject" + AllowedRedirectURIs = [ + "http://localhost:8550/oidc/callback", + "http://localhost:8500/ui/oidc/callback" + ] + BoundAudiences = [ + "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt" + ] + ClaimMappings = { + "http://example.com/first_name" = "first_name" + "http://example.com/last_name" = "last_name" } + ListClaimMappings = { + "http://consul.com/groups" = "groups" + } + OIDCClientID = "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt" + OIDCClientSecret = "...(omitted)..." + OIDCDiscoveryURL = "https://my-corp-app-name.auth0.com/" }) } ``` -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) The name of the ACL auth method. -* `type` - (Required) The type of the ACL auth method. -* `display_name` - (Optional) An optional name to use instead of the name - attribute when displaying information about this auth method. -* `max_token_ttl` - (Optional) The maximum life of any token created by this - auth method. -* `token_locality` - (Optional) The kind of token that this auth method - produces. This can be either 'local' or 'global'. -* `description` - (Optional) A free form human readable description of the auth method. -* `config_json` - (Required) The raw configuration for this ACL auth method. -* `config` - (Optional) The raw configuration for this ACL auth method. This - attribute is deprecated and will be removed in a future version. `config_json` - should be used instead. -* `namespace` - (Optional, Enterprise Only) The namespace in which to create the auth method. -* `partition` - (Optional, Enterprise Only) The partition the ACL auth method is associated with. -* `namespace_rule` - (Optional, Enterprise Only) A set of rules that control - which namespace tokens created via this auth method will be created within. - -Each `namespace_rule` can have the following attributes: -* `selector` - (Optional) Specifies the expression used to match this namespace - rule against valid identities returned from an auth method validation. - Defaults to `""`. -* `bind_namespace` - (Required) If the namespace rule's `selector` matches then - this is used to control the namespace where the token is created. - -## Attributes Reference - -The following attributes are exported: - -* `id` - The ID of the the auth method. -* `name` - The name of the ACL auth method. -* `type` - The type of the ACL auth method. -* `display_name` - An optional name to use instead of the name attribute when - displaying information about this auth method. -* `max_token_ttl` - The maximum life of any token created by this auth method. -* `token_locality` - The kind of token that this auth method produces. This can - be either 'local' or 'global'. -* `description` - A free form human readable description of the auth method. -* `config_json` - The raw configuration for this ACL auth method. -* `config` - The raw configuration for this ACL auth method. This attribute is - deprecated and will be removed in a future version. If the configuration is - too complex to be represented as a map of strings it will be blank. - `config_json` should be used instead. -* `namespace` - (Enterprise Only) The namespace in which to create the auth method. -* `namespace_rule` - (Enterprise Only) A set of rules that control which - namespace tokens created via this auth method will be created within. + + +## Schema + +### Required + +- `name` (String) The name of the ACL auth method. +- `type` (String) The type of the ACL auth method. + +### Optional + +- `config` (Map of String, Deprecated) The raw configuration for this ACL auth method. +- `config_json` (String) The raw configuration for this ACL auth method. +- `description` (String) A free form human readable description of the auth method. +- `display_name` (String) An optional name to use instead of the name attribute when displaying information about this auth method. +- `max_token_ttl` (String) The maximum life of any token created by this auth method. **This attribute is required and must be set to a nonzero for the OIDC auth method.** +- `namespace` (String) The namespace in which to create the auth method. +- `namespace_rule` (Block List) A set of rules that control which namespace tokens created via this auth method will be created within. (see [below for nested schema](#nestedblock--namespace_rule)) +- `partition` (String) The partition the ACL auth method is associated with. +- `token_locality` (String) The kind of token that this auth method produces. This can be either 'local' or 'global'. + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `namespace_rule` + +Required: + +- `bind_namespace` (String) If the namespace rule's `selector` matches then this is used to control the namespace where the token is created. + +Optional: + +- `selector` (String) Specifies the expression used to match this namespace rule against valid identities returned from an auth method validation. + + diff --git a/docs/resources/peering.md b/docs/resources/peering.md index 8d1025e5..4230edd7 100644 --- a/docs/resources/peering.md +++ b/docs/resources/peering.md @@ -73,5 +73,3 @@ resource "consul_peering" "eu-us" { - `peer_server_addresses` (List of String) - `peer_server_name` (String) - `state` (String) - - diff --git a/docs/resources/peering_token.md b/docs/resources/peering_token.md index 0ae7341b..a80a4674 100644 --- a/docs/resources/peering_token.md +++ b/docs/resources/peering_token.md @@ -43,5 +43,3 @@ resource "consul_peering_token" "token" { - `id` (String) The ID of this resource. - `peering_token` (String, Sensitive) The generated peering token - - diff --git a/examples/resources/consul_acl_auth_method/jwt.tf b/examples/resources/consul_acl_auth_method/jwt.tf new file mode 100644 index 00000000..6e991464 --- /dev/null +++ b/examples/resources/consul_acl_auth_method/jwt.tf @@ -0,0 +1,25 @@ +resource "consul_acl_auth_method" "oidc" { + name = "auth0" + type = "oidc" + max_token_ttl = "5m" + + config_json = jsonencode({ + AllowedRedirectURIs = [ + "http://localhost:8550/oidc/callback", + "http://localhost:8500/ui/oidc/callback" + ] + BoundAudiences = [ + "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt" + ] + ClaimMappings = { + "http://example.com/first_name" = "first_name" + "http://example.com/last_name" = "last_name" + } + ListClaimMappings = { + "http://consul.com/groups" = "groups" + } + OIDCClientID = "V1RPi2MYptMV1RPi2MYptMV1RPi2MYpt" + OIDCClientSecret = "...(omitted)..." + OIDCDiscoveryURL = "https://my-corp-app-name.auth0.com/" + }) +} diff --git a/examples/resources/consul_acl_auth_method/kubernetes.tf b/examples/resources/consul_acl_auth_method/kubernetes.tf new file mode 100644 index 00000000..e39b04ed --- /dev/null +++ b/examples/resources/consul_acl_auth_method/kubernetes.tf @@ -0,0 +1,11 @@ +resource "consul_acl_auth_method" "minikube" { + name = "minikube" + type = "kubernetes" + description = "dev minikube cluster" + + config_json = jsonencode({ + Host = "https://192.0.2.42:8443" + CACert = "-----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n" + ServiceAccountJWT = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9..." + }) +} diff --git a/templates/resources/acl_auth_method.md b/templates/resources/acl_auth_method.md deleted file mode 100644 index 455ec38f..00000000 --- a/templates/resources/acl_auth_method.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -layout: "consul" -page_title: "Consul: consul_acl_auth_method" -sidebar_current: "docs-consul-resource-acl-auth-method" -description: |- - Allows Terraform to create an ACL auth method ---- - -# consul_acl_auth_method - -Starting with Consul 1.5.0, the consul_acl_auth_method resource can be used to -managed [Consul ACL auth methods](https://www.consul.io/docs/acl/auth-methods). - - -## Example Usage - -Define a `kubernetes` auth method: -```hcl -resource "consul_acl_auth_method" "minikube" { - name = "minikube" - type = "kubernetes" - description = "dev minikube cluster" - - config_json = jsonencode({ - Host = "https://192.0.2.42:8443" - CACert = "-----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n" - ServiceAccountJWT = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9..." - }) -} -``` - -Define a `jwt` auth method: -```hcl -resource "consul_acl_auth_method" "minikube" { - name = "auth_method" - type = "jwt" - - config_json = jsonencode({ - JWKSURL = "https://example.com/identity/oidc/.well-known/keys" - JWTSupportedAlgs = "RS256" - BoundIssuer = "https://example.com" - ClaimMappings = { - subject = "subject" - } - }) -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) The name of the ACL auth method. -* `type` - (Required) The type of the ACL auth method. -* `display_name` - (Optional) An optional name to use instead of the name - attribute when displaying information about this auth method. -* `max_token_ttl` - (Optional) The maximum life of any token created by this - auth method. -* `token_locality` - (Optional) The kind of token that this auth method - produces. This can be either 'local' or 'global'. -* `description` - (Optional) A free form human readable description of the auth method. -* `config_json` - (Required) The raw configuration for this ACL auth method. -* `config` - (Optional) The raw configuration for this ACL auth method. This - attribute is deprecated and will be removed in a future version. `config_json` - should be used instead. -* `namespace` - (Optional, Enterprise Only) The namespace in which to create the auth method. -* `partition` - (Optional, Enterprise Only) The partition the ACL auth method is associated with. -* `namespace_rule` - (Optional, Enterprise Only) A set of rules that control - which namespace tokens created via this auth method will be created within. - -Each `namespace_rule` can have the following attributes: -* `selector` - (Optional) Specifies the expression used to match this namespace - rule against valid identities returned from an auth method validation. - Defaults to `""`. -* `bind_namespace` - (Required) If the namespace rule's `selector` matches then - this is used to control the namespace where the token is created. - -## Attributes Reference - -The following attributes are exported: - -* `id` - The ID of the the auth method. -* `name` - The name of the ACL auth method. -* `type` - The type of the ACL auth method. -* `display_name` - An optional name to use instead of the name attribute when - displaying information about this auth method. -* `max_token_ttl` - The maximum life of any token created by this auth method. -* `token_locality` - The kind of token that this auth method produces. This can - be either 'local' or 'global'. -* `description` - A free form human readable description of the auth method. -* `config_json` - The raw configuration for this ACL auth method. -* `config` - The raw configuration for this ACL auth method. This attribute is - deprecated and will be removed in a future version. If the configuration is - too complex to be represented as a map of strings it will be blank. - `config_json` should be used instead. -* `namespace` - (Enterprise Only) The namespace in which to create the auth method. -* `namespace_rule` - (Enterprise Only) A set of rules that control which - namespace tokens created via this auth method will be created within. diff --git a/templates/resources/acl_auth_method.md.tmpl b/templates/resources/acl_auth_method.md.tmpl new file mode 100644 index 00000000..b976ced3 --- /dev/null +++ b/templates/resources/acl_auth_method.md.tmpl @@ -0,0 +1,32 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +Define a `kubernetes` auth method: + +{{ tffile "examples/resources/consul_acl_auth_method/kubernetes.tf" }} + + +Define a `jwt` auth method: + +{{ tffile "examples/resources/consul_acl_auth_method/jwt.tf" }} + + +{{ .SchemaMarkdown | trimspace }} + +{{ if .HasImport -}} +## Import + +Import is supported using the following syntax: + +{{ printf "{{codefile \"shell\" %q}}" .ImportFile }} +{{- end }} From c0afbe954a37303a9ea176b6a72b7b05a9d7a7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Sun, 8 Oct 2023 23:05:27 -0700 Subject: [PATCH 84/89] Fix consul_config_entry_service_router tests --- GNUmakefile | 2 +- .../resource_consul_config_entry_concrete.go | 4 +- ...ce_consul_config_entry_service_defaults.go | 5 +- ..._consul_config_entry_service_intentions.go | 3 +- ...ce_consul_config_entry_service_resolver.go | 9 +- ...urce_consul_config_entry_service_router.go | 574 +++++++++--------- ...sul_config_entry_service_router_ce_test.go | 213 ++++++- ...ce_consul_config_entry_service_splitter.go | 4 +- .../config_entry_service_defaults.md | 9 - .../config_entry_service_intentions.md | 113 ++++ .../config_entry_service_resolver.md | 140 +++++ docs/resources/config_entry_service_router.md | 122 ++++ .../config_entry_service_splitter.md | 2 - 13 files changed, 870 insertions(+), 330 deletions(-) create mode 100644 docs/resources/config_entry_service_intentions.md create mode 100644 docs/resources/config_entry_service_resolver.md create mode 100644 docs/resources/config_entry_service_router.md diff --git a/GNUmakefile b/GNUmakefile index 1b915db2..68cdf0d1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -22,7 +22,7 @@ test: fmtcheck xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 testacc: fmtcheck - TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m + TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 2m vet: @echo "go vet ." diff --git a/consul/resource_consul_config_entry_concrete.go b/consul/resource_consul_config_entry_concrete.go index abd1d11f..ad4707ea 100644 --- a/consul/resource_consul_config_entry_concrete.go +++ b/consul/resource_consul_config_entry_concrete.go @@ -18,7 +18,7 @@ type ConfigEntryImplementation interface { GetDescription() string GetSchema() map[string]*schema.Schema Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) - Write(ce consulapi.ConfigEntry, sw *stateWriter) error + Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error } func resourceFromConfigEntryImplementation(c ConfigEntryImplementation) *schema.Resource { @@ -108,7 +108,7 @@ func configEntryImplementationRead(impl ConfigEntryImplementation) func(d *schem } sw := newStateWriter(d) - if err := impl.Write(ce, sw); err != nil { + if err := impl.Write(ce, d, sw); err != nil { return err } return sw.error() diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go index 27539a78..7e93fc12 100644 --- a/consul/resource_consul_config_entry_service_defaults.go +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -5,9 +5,10 @@ package consul import ( "fmt" + "time" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "time" ) type serviceDefaults struct{} @@ -736,7 +737,7 @@ func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return configEntry, nil } -func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { +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()) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index 9facc3dc..e769323f 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -5,6 +5,7 @@ package consul import ( "fmt" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -454,7 +455,7 @@ func (s *serviceIntentions) Decode(d *schema.ResourceData) (consulapi.ConfigEntr return configEntry, nil } -func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { +func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error { si, ok := ce.(*consulapi.ServiceIntentionsConfigEntry) if !ok { return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceRouter, ce.GetKind()) diff --git a/consul/resource_consul_config_entry_service_resolver.go b/consul/resource_consul_config_entry_service_resolver.go index 4fede46d..4848075d 100644 --- a/consul/resource_consul_config_entry_service_resolver.go +++ b/consul/resource_consul_config_entry_service_resolver.go @@ -6,13 +6,14 @@ package consul import ( "bytes" "fmt" - consulapi "github.com/hashicorp/consul/api" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "reflect" "sort" "strings" "time" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) type serviceResolver struct{} @@ -524,7 +525,7 @@ func (s *serviceResolver) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return configEntry, nil } -func (s *serviceResolver) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { +func (s *serviceResolver) Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error { sr, ok := ce.(*consulapi.ServiceResolverConfigEntry) if !ok { return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceResolver, ce.GetKind()) diff --git a/consul/resource_consul_config_entry_service_router.go b/consul/resource_consul_config_entry_service_router.go index f11f5dc2..ed0ff2df 100644 --- a/consul/resource_consul_config_entry_service_router.go +++ b/consul/resource_consul_config_entry_service_router.go @@ -5,9 +5,10 @@ package consul import ( "fmt" + "time" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "time" ) type serviceRouter struct{} @@ -53,13 +54,15 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "match": { - Type: schema.TypeSet, + Type: schema.TypeList, + MaxItems: 1, Description: "Describes a set of criteria that Consul compares incoming L7 traffic with.", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "http": { - Type: schema.TypeSet, + Type: schema.TypeList, + MaxItems: 1, Description: "Specifies a set of HTTP criteria used to evaluate incoming L7 traffic for matches.", Optional: true, Elem: &schema.Resource{ @@ -99,7 +102,7 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "present": { Type: schema.TypeBool, Optional: true, - Description: "Specifies that a request matches when the value in the Name field is present anywhere in the HTTP header.", + Description: "Specifies that a request matches when the value in the `name` argument is present anywhere in the HTTP header.", }, "exact": { Type: schema.TypeString, @@ -143,7 +146,7 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "present": { Type: schema.TypeBool, Optional: true, - Description: "Specifies that a request matches when the value in the Name field is present anywhere in the HTTP query parameter.", + Description: "Specifies that a request matches when the value in the `name` argument is present anywhere in the HTTP query parameter.", }, "exact": { Type: schema.TypeString, @@ -165,7 +168,8 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { }, }, "destination": { - Type: schema.TypeSet, + Type: schema.TypeList, + MaxItems: 1, Optional: true, Description: "Specifies the target service to route matching requests to, as well as behavior for the request to follow when routed.", Elem: &schema.Resource{ @@ -178,7 +182,7 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "service_subset": { Type: schema.TypeString, Optional: true, - Description: "Specifies a named subset of the given service to resolve instead of the one defined as that service's DefaultSubset in the service resolver configuration entry.", + Description: "Specifies a named subset of the given service to resolve instead of the one defined as that service's `default_subset` in the service resolver configuration entry.", }, "namespace": { Type: schema.TypeString, @@ -210,13 +214,11 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { "num_retries": { Type: schema.TypeInt, Optional: true, - Default: 0, Description: "Specifies the number of times to retry the request when a retry condition occurs.", }, "retry_on_connect_failure": { Type: schema.TypeBool, Optional: true, - Default: false, Description: "Specifies that connection failure errors that trigger a retry request.", }, "retry_on": { @@ -232,7 +234,8 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { Description: "Specifies a list of integers for HTTP response status codes that trigger a retry request.", }, "request_headers": { - Type: schema.TypeSet, + Type: schema.TypeList, + MaxItems: 1, Optional: true, Description: "Specifies a set of HTTP-specific header modification rules applied to requests routed with the service router.", Elem: &schema.Resource{ @@ -259,7 +262,8 @@ func (s *serviceRouter) GetSchema() map[string]*schema.Schema { }, }, "response_headers": { - Type: schema.TypeSet, + Type: schema.TypeList, + MaxItems: 1, Optional: true, Description: "Specifies a set of HTTP-specific header modification rules applied to responses routed with the service router.", Elem: &schema.Resource{ @@ -307,193 +311,136 @@ func (s *serviceRouter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, e configEntry.Meta[k] = v.(string) } - routes := d.Get("routes") - if routes != nil { - routeList := routes.([]interface{}) - serviceRoutesList := make([]consulapi.ServiceRoute, len(routeList)) - for indx, r := range routeList { - routListMap := r.(map[string]interface{}) - matchList := routListMap["match"].(*schema.Set).List() - if len(matchList) > 0 { - matchMap := matchList[0].(map[string]interface{}) - matchHTTPMap := matchMap["http"].(*schema.Set).List() - if len(matchHTTPMap) > 0 { - matchHTTP := matchHTTPMap[0].(map[string]interface{}) - var matchRoute *consulapi.ServiceRouteMatch - matchRoute = new(consulapi.ServiceRouteMatch) - var serviceRouteHTTPMatch *consulapi.ServiceRouteHTTPMatch - serviceRouteHTTPMatch = new(consulapi.ServiceRouteHTTPMatch) - serviceRouteHTTPMatch.PathExact = matchHTTP["path_exact"].(string) - serviceRouteHTTPMatch.PathPrefix = matchHTTP["path_prefix"].(string) - serviceRouteHTTPMatch.PathRegex = matchHTTP["path_regex"].(string) - methods := make([]string, 0) - for _, v := range matchHTTP["methods"].([]interface{}) { - methods = append(methods, v.(string)) - } - serviceRouteHTTPMatch.Methods = methods - headers := make([]consulapi.ServiceRouteHTTPMatchHeader, 0) - matchHeaders := matchHTTP["header"].([]interface{}) - for _, h := range matchHeaders { - header := h.(map[string]interface{}) - matchHeader := &consulapi.ServiceRouteHTTPMatchHeader{ - Name: header["name"].(string), - Present: header["present"].(bool), - Exact: header["exact"].(string), - Prefix: header["prefix"].(string), - Suffix: header["suffix"].(string), - Regex: header["regex"].(string), - Invert: header["present"].(bool), - } - headers = append(headers, *matchHeader) - } - serviceRouteHTTPMatch.Header = headers - queryParam := matchHTTP["query_param"].([]interface{}) - queryParamList := make([]consulapi.ServiceRouteHTTPMatchQueryParam, len(queryParam)) - for index, q := range queryParam { - queryParamMap := q.(map[string]interface{}) - queryParamList[index].Name = queryParamMap["name"].(string) - queryParamList[index].Regex = queryParamMap["regex"].(string) - queryParamList[index].Present = queryParamMap["present"].(bool) - queryParamList[index].Exact = queryParamMap["exact"].(string) - } - serviceRouteHTTPMatch.QueryParam = queryParamList - matchRoute.HTTP = serviceRouteHTTPMatch - serviceRoutesList[indx].Match = matchRoute + for i, r := range d.Get("routes").([]interface{}) { + route := r.(map[string]interface{}) + + sr := consulapi.ServiceRoute{ + Destination: &consulapi.ServiceRouteDestination{}, + } + + for _, m := range route["match"].([]interface{}) { + match := m.(map[string]interface{}) + + for _, h := range match["http"].([]interface{}) { + http := h.(map[string]interface{}) + + sr.Match = &consulapi.ServiceRouteMatch{ + HTTP: &consulapi.ServiceRouteHTTPMatch{ + PathExact: http["path_exact"].(string), + PathPrefix: http["path_prefix"].(string), + PathRegex: http["path_regex"].(string), + }, + } + + for _, method := range http["methods"].([]interface{}) { + sr.Match.HTTP.Methods = append(sr.Match.HTTP.Methods, method.(string)) + } + + for _, h := range http["header"].([]interface{}) { + header := h.(map[string]interface{}) + + sr.Match.HTTP.Header = append(sr.Match.HTTP.Header, consulapi.ServiceRouteHTTPMatchHeader{ + Name: header["name"].(string), + Exact: header["exact"].(string), + Prefix: header["prefix"].(string), + Suffix: header["suffix"].(string), + Regex: header["regex"].(string), + Present: header["present"].(bool), + Invert: header["invert"].(bool), + }) + } + + for _, q := range http["query_param"].([]interface{}) { + queryParam := q.(map[string]interface{}) + + sr.Match.HTTP.QueryParam = append(sr.Match.HTTP.QueryParam, consulapi.ServiceRouteHTTPMatchQueryParam{ + Name: queryParam["name"].(string), + Exact: queryParam["exact"].(string), + Regex: queryParam["regex"].(string), + Present: queryParam["present"].(bool), + }) + } + } + } + + for _, d := range route["destination"].([]interface{}) { + destination := d.(map[string]interface{}) + + sr.Destination = &consulapi.ServiceRouteDestination{ + Service: destination["service"].(string), + ServiceSubset: destination["service_subset"].(string), + Namespace: destination["namespace"].(string), + Partition: destination["partition"].(string), + PrefixRewrite: destination["prefix_rewrite"].(string), + NumRetries: uint32(destination["num_retries"].(int)), + RetryOnConnectFailure: destination["retry_on_connect_failure"].(bool), + } + + parseDuration := func(name string) (time.Duration, error) { + dur, err := time.ParseDuration(destination[name].(string)) + if err != nil { + return 0, fmt.Errorf("failed to parse routes[%d].destination.%s: %w", i, name, err) + } + return dur, nil + } + + dur, err := parseDuration("request_timeout") + if err != nil { + return nil, err + } + sr.Destination.RequestTimeout = dur + + dur, err = parseDuration("idle_timeout") + if err != nil { + return nil, err + } + sr.Destination.IdleTimeout = dur + + for _, r := range destination["retry_on_status_codes"].([]interface{}) { + sr.Destination.RetryOnStatusCodes = append(sr.Destination.RetryOnStatusCodes, uint32(r.(int))) + } + + for _, r := range destination["retry_on"].([]interface{}) { + sr.Destination.RetryOn = append(sr.Destination.RetryOn, r.(string)) + } + + parseHTTPHeaderModifiers := func(name string) *consulapi.HTTPHeaderModifiers { + if len(destination[name].([]interface{})) == 0 { + return nil + } + + headers := destination[name].([]interface{})[0].(map[string]interface{}) + result := &consulapi.HTTPHeaderModifiers{ + Add: map[string]string{}, + Set: map[string]string{}, + } + + for k, v := range headers["add"].(map[string]interface{}) { + result.Add[k] = v.(string) + } + + for k, v := range headers["set"].(map[string]interface{}) { + result.Add[k] = v.(string) } - var destination *consulapi.ServiceRouteDestination - destination = new(consulapi.ServiceRouteDestination) - destinationList := (routListMap["destination"].(*schema.Set)).List() - if len(destinationList) > 0 { - destinationMap := destinationList[0].(map[string]interface{}) - destination.Service = destinationMap["service"].(string) - destination.ServiceSubset = destinationMap["service_subset"].(string) - destination.Namespace = destinationMap["namespace"].(string) - destination.Partition = destinationMap["partition"].(string) - destination.PrefixRewrite = destinationMap["prefix_rewrite"].(string) - if destinationMap["request_timeout"] != "" { - requestTimeout, err := time.ParseDuration(destinationMap["request_timeout"].(string)) - if err != nil { - return nil, err - } - destination.RequestTimeout = requestTimeout - } - if destinationMap["idle_timeout"] != "" { - idleTimeout, err := time.ParseDuration(destinationMap["idle_timeout"].(string)) - if err != nil { - return nil, err - } - destination.IdleTimeout = idleTimeout - } - destination.NumRetries = uint32(destinationMap["num_retries"].(int)) - destination.RetryOnConnectFailure = destinationMap["retry_on_connect_failure"].(bool) - retryOnList := make([]string, 0) - for _, v := range destinationMap["retry_on"].([]interface{}) { - retryOnList = append(retryOnList, v.(string)) - } - destination.RetryOn = retryOnList - retryOnCodes := make([]uint32, 0) - for _, v := range destinationMap["retry_on_status_codes"].([]interface{}) { - retryOnCodes = append(retryOnCodes, v.(uint32)) - } - destination.RetryOnStatusCodes = retryOnCodes - var requestMap *consulapi.HTTPHeaderModifiers - requestMap = new(consulapi.HTTPHeaderModifiers) - addMap := make(map[string]string) - setMap := make(map[string]string) - if destinationMap["request_headers"] != nil { - reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() - if len(reqHeadersList) > 0 { - destinationAddMap := reqHeadersList[0].(map[string]interface{})["add"] - if destinationAddMap != nil { - for k, v := range destinationAddMap.(map[string]string) { - addMap[k] = v - } - requestMap.Add = addMap - } - } - } - if destinationMap["request_headers"] != nil { - reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() - if len(reqHeadersList) > 0 { - destinationSetMap := reqHeadersList[0].(map[string]interface{})["set"] - if destinationSetMap != nil { - for k, v := range destinationSetMap.(map[string]string) { - setMap[k] = v - } - requestMap.Set = setMap - } - } - } - removeList := make([]string, 0) - if destinationMap["request_headers"] != nil { - reqHeadersList := destinationMap["request_headers"].(*schema.Set).List() - if len(reqHeadersList) > 0 { - destinationRemoveList := reqHeadersList[0].(map[string]interface{})["remove"] - if destinationRemoveList != nil && len(destinationRemoveList.([]string)) > 0 { - for _, v := range destinationRemoveList.([]string) { - removeList = append(removeList, v) - } - } - } - } - if len(removeList) > 0 { - requestMap.Remove = removeList - } - destination.RequestHeaders = requestMap - var responseMap *consulapi.HTTPHeaderModifiers - responseMap = new(consulapi.HTTPHeaderModifiers) - addMap = make(map[string]string) - setMap = make(map[string]string) - if destinationMap["response_headers"] != nil { - resHeadersList := destinationMap["response_headers"].(*schema.Set).List() - if len(resHeadersList) > 0 { - destinationAddMap := resHeadersList[0].(map[string]interface{})["add"] - if destinationAddMap != nil { - for k, v := range destinationAddMap.(map[string]string) { - addMap[k] = v - } - responseMap.Add = addMap - } - } - } - if destinationMap["response_headers"] != nil { - resHeadersList := destinationMap["response_headers"].(*schema.Set).List() - if len(resHeadersList) > 0 { - destinationSetMap := resHeadersList[0].(map[string]interface{})["set"] - if destinationSetMap != nil { - for k, v := range destinationSetMap.(map[string]string) { - setMap[k] = v - } - responseMap.Set = setMap - } - } - } - removeList = make([]string, 0) - if destinationMap["response_headers"] != nil { - resHeadersList := destinationMap["response_headers"].(*schema.Set).List() - if len(resHeadersList) > 0 { - destinationRemoveList := resHeadersList[0].(map[string]interface{})["remove"] - if destinationRemoveList != nil && len(destinationRemoveList.([]string)) > 0 { - for _, v := range destinationRemoveList.([]string) { - removeList = append(removeList, v) - } - } - } - } - if len(removeList) > 0 { - responseMap.Remove = removeList - } - destination.ResponseHeaders = responseMap - serviceRoutesList[indx].Destination = destination + + for _, v := range headers["remove"].([]interface{}) { + result.Remove = append(result.Remove, v.(string)) } + + return result } + + sr.Destination.RequestHeaders = parseHTTPHeaderModifiers("request_headers") + sr.Destination.ResponseHeaders = parseHTTPHeaderModifiers("response_headers") } - configEntry.Routes = serviceRoutesList + + configEntry.Routes = append(configEntry.Routes, sr) } + return configEntry, nil } -func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { +func (s *serviceRouter) Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error { sr, ok := ce.(*consulapi.ServiceRouterConfigEntry) if !ok { return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceDefaults, ce.GetKind()) @@ -503,123 +450,168 @@ func (s *serviceRouter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { sw.set("partition", sr.Partition) sw.set("namespace", sr.Namespace) - meta := make(map[string]interface{}) + meta := map[string]interface{}{} for k, v := range sr.Meta { meta[k] = v } sw.set("meta", meta) routes := make([]map[string]interface{}, 0) - if len(sr.Routes) > 0 { - route := make(map[string]interface{}) - for _, routesValue := range sr.Routes { - match := make([]map[string]interface{}, 1) - match[0] = make(map[string]interface{}) - matchHTTP := make([]map[string]interface{}, 1) - matchHTTP[0] = make(map[string]interface{}) - matchHTTP[0]["path_exact"] = routesValue.Match.HTTP.PathExact - matchHTTP[0]["path_prefix"] = routesValue.Match.HTTP.PathPrefix - matchHTTP[0]["path_regex"] = routesValue.Match.HTTP.PathRegex - matchHTTP[0]["methods"] = routesValue.Match.HTTP.Methods - headerList := make([]map[string]interface{}, 0) - for _, headerValue := range routesValue.Match.HTTP.Header { - headerMap := make(map[string]interface{}) - headerMap["name"] = headerValue.Name - headerMap["present"] = headerValue.Present - headerMap["exact"] = headerValue.Exact - headerMap["prefix"] = headerValue.Prefix - headerMap["suffix"] = headerValue.Suffix - headerMap["regex"] = headerValue.Regex - headerMap["invert"] = headerValue.Invert - headerList = append(headerList, headerMap) + for _, route := range sr.Routes { + result := map[string]interface{}{} + + var http map[string]interface{} + + shouldSet := func() bool { + isEmpty := route.Match == nil || route.Match.HTTP == nil || (route.Match.HTTP.PathExact == "" && + route.Match.HTTP.PathPrefix == "" && + route.Match.HTTP.PathRegex == "" && + len(route.Match.HTTP.Header) == 0 && + len(route.Match.HTTP.QueryParam) == 0 && + len(route.Match.HTTP.Methods) == 0) + + if !isEmpty { + return true } - queryParamList := make([]map[string]interface{}, 0) - for _, queryParamValue := range routesValue.Match.HTTP.QueryParam { - queryParamMap := make(map[string]interface{}) - queryParamMap["name"] = queryParamValue.Name - queryParamMap["present"] = queryParamValue.Present - queryParamMap["exact"] = queryParamValue.Exact - queryParamMap["regex"] = queryParamValue.Regex - queryParamList = append(queryParamList, queryParamMap) + + routes := d.Get("routes").([]interface{}) + if len(routes) == 0 { + return false } - matchHTTP[0]["header"] = headerList - matchHTTP[0]["query_param"] = queryParamList - match[0]["http"] = matchHTTP - destination := make([]map[string]interface{}, 1) - destination[0] = make(map[string]interface{}) - if routesValue.Destination != nil { - destination[0]["service"] = routesValue.Destination.Service - destination[0]["service_subset"] = routesValue.Destination.ServiceSubset - destination[0]["namespace"] = routesValue.Destination.Namespace - destination[0]["partition"] = routesValue.Destination.Partition - destination[0]["prefix_rewrite"] = routesValue.Destination.PrefixRewrite - destination[0]["request_timeout"] = routesValue.Destination.RequestTimeout.String() - destination[0]["idle_timeout"] = routesValue.Destination.IdleTimeout.String() - destination[0]["num_retries"] = routesValue.Destination.NumRetries - destination[0]["retry_on_connect_failure"] = routesValue.Destination.RetryOnConnectFailure - destination[0]["retry_on"] = routesValue.Destination.RetryOn - destination[0]["retry_on_status_codes"] = routesValue.Destination.RetryOnStatusCodes - requestHeaders := make([]map[string]interface{}, 1) - requestHeaders[0] = make(map[string]interface{}) - addMap := make(map[string]interface{}) - if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Add != nil { - for k, v := range routesValue.Destination.RequestHeaders.Add { - addMap[k] = v - } - } - requestHeaders[0]["add"] = addMap - setMap := make(map[string]interface{}) - if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Set != nil { - for k, v := range routesValue.Destination.RequestHeaders.Set { - setMap[k] = v - } - } - requestHeaders[0]["set"] = setMap - removeList := make([]string, 0) - if routesValue.Destination.RequestHeaders != nil && routesValue.Destination.RequestHeaders.Remove != nil { - for _, v := range routesValue.Destination.RequestHeaders.Remove { - removeList = append(removeList, v) - } - } - if len(removeList) > 0 { - requestHeaders[0]["remove"] = removeList + match := routes[0].(map[string]interface{})["match"].([]interface{}) + if len(match) == 0 { + return false + } + http := match[0].(map[string]interface{})["http"].([]interface{}) + if len(http) == 0 { + return false + } + if len(http[0].(map[string]interface{})["header"].([]interface{})) != 0 { + return true + } + if len(http[0].(map[string]interface{})["query_param"].([]interface{})) != 0 { + return true + } + + return false + } + + if shouldSet() { + http = map[string]interface{}{ + "path_exact": route.Match.HTTP.PathExact, + "path_prefix": route.Match.HTTP.PathPrefix, + "path_regex": route.Match.HTTP.PathRegex, + "methods": route.Match.HTTP.Methods, + } + + header := []interface{}{} + for _, h := range route.Match.HTTP.Header { + header = append(header, map[string]interface{}{ + "name": h.Name, + "present": h.Present, + "exact": h.Exact, + "prefix": h.Prefix, + "suffix": h.Suffix, + "regex": h.Regex, + "invert": h.Invert, + }) + } + http["header"] = header + + queryParam := []interface{}{} + for _, q := range route.Match.HTTP.QueryParam { + queryParam = append(queryParam, map[string]interface{}{ + "name": q.Name, + "present": q.Present, + "exact": q.Exact, + "regex": q.Regex, + }) + } + http["query_param"] = queryParam + + result["match"] = []interface{}{ + map[string]interface{}{ + "http": []interface{}{http}, + }, + } + } + + shouldSet = func() bool { + isEmpty := route.Destination == nil || (route.Destination.Service == "" && + route.Destination.ServiceSubset == "" && + route.Destination.Namespace == "" && + route.Destination.Partition == "" && + route.Destination.PrefixRewrite == "" && + route.Destination.RequestTimeout == 0 && + route.Destination.IdleTimeout == 0 && + route.Destination.NumRetries == 0 && + !route.Destination.RetryOnConnectFailure && + len(route.Destination.RetryOnStatusCodes) == 0 && + len(route.Destination.RetryOn) == 0 && (route.Destination.RequestHeaders == nil || len(route.Destination.RequestHeaders.Add)+len(route.Destination.RequestHeaders.Set)+len(route.Destination.RequestHeaders.Remove) == 0) && + route.Destination.ResponseHeaders == nil) + + if !isEmpty { + return true + } + + routes := d.Get("routes").([]interface{}) + if len(routes) == 0 { + return false + } + destination := routes[0].(map[string]interface{})["destination"].([]interface{}) + return len(destination) != 0 + } + + if shouldSet() { + destination := map[string]interface{}{ + "service": route.Destination.Service, + "service_subset": route.Destination.ServiceSubset, + "namespace": route.Destination.Namespace, + "partition": route.Destination.Partition, + "prefix_rewrite": route.Destination.PrefixRewrite, + "request_timeout": route.Destination.RequestTimeout.String(), + "idle_timeout": route.Destination.IdleTimeout.String(), + "num_retries": route.Destination.NumRetries, + "retry_on_connect_failure": route.Destination.RetryOnConnectFailure, + "retry_on": route.Destination.RetryOn, + "retry_on_status_codes": route.Destination.RetryOnStatusCodes, + } + + convertHeaders := func(headers *consulapi.HTTPHeaderModifiers) []interface{} { + if headers == nil { + return []interface{}{} } - destination[0]["request_headers"] = requestHeaders - responseHeaders := make([]map[string]interface{}, 1) - responseHeaders[0] = make(map[string]interface{}) - responseHeaders[0]["add"] = make(map[string]interface{}) - addMap = make(map[string]interface{}) - if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Add != nil { - for k, v := range routesValue.Destination.ResponseHeaders.Add { - addMap[k] = v - } + + add := map[string]interface{}{} + for k, v := range headers.Add { + add[k] = v } - responseHeaders[0]["add"] = addMap - setMap = make(map[string]interface{}) - if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Set != nil { - for k, v := range routesValue.Destination.ResponseHeaders.Set { - setMap[k] = v - } + + set := map[string]interface{}{} + for k, v := range headers.Set { + set[k] = v } - responseHeaders[0]["set"] = setMap - removeList = make([]string, 0) - if routesValue.Destination.ResponseHeaders != nil && routesValue.Destination.ResponseHeaders.Remove != nil { - for _, v := range routesValue.Destination.ResponseHeaders.Remove { - removeList = append(removeList, v) - } + + remove := []interface{}{} + for _, v := range headers.Remove { + remove = append(remove, v) } - if len(removeList) > 0 { - responseHeaders[0]["remove"] = removeList + + return []interface{}{ + map[string]interface{}{ + "add": add, + "set": set, + "remove": remove, + }, } - destination[0]["response_headers"] = responseHeaders } - route["match"] = match - route["destination"] = destination + destination["request_headers"] = convertHeaders(route.Destination.RequestHeaders) + result["destination"] = []interface{}{destination} } - routes = append(routes, route) - } + routes = append(routes, result) + } sw.set("routes", routes) - return nil + return sw.error() } diff --git a/consul/resource_consul_config_entry_service_router_ce_test.go b/consul/resource_consul_config_entry_service_router_ce_test.go index 9dec2c9a..c604142d 100644 --- a/consul/resource_consul_config_entry_service_router_ce_test.go +++ b/consul/resource_consul_config_entry_service_router_ce_test.go @@ -16,23 +16,131 @@ func TestAccConsulConfigEntryServiceRouterCETest(t *testing.T) { PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, Providers: providers, Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceRouterCE_Empty, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "0"), + ), + }, { Config: testConsulConfigEntryServiceRouterCE, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", ""), resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.365255188.http.#", "1"), resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.idle_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.num_retries", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.prefix_rewrite", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.response_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_connect_failure", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_status_codes.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service", "admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service_subset", ""), resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "1"), - resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.365255188.http.3609927257.path_prefix", "/admin"), - resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.1670225453.retry_on_connect_failure", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.header.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.methods.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_exact", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_prefix", "/admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_regex", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.query_param.#", "0"), + ), + }, + { + Config: testConsulConfigEntryServiceRouterCE_noMatch, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.idle_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.num_retries", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.prefix_rewrite", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.response_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_connect_failure", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_status_codes.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service", "admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service_subset", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "0"), + ), + }, + { + Config: testConsulConfigEntryServiceRouterCE_noDestination, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.header.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.methods.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_exact", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_prefix", "/admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_regex", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.query_param.#", "0"), ), }, }, }) } -const testConsulConfigEntryServiceRouterCE = ` +const ( + testConsulConfigEntryServiceRouterCE_Empty = ` + resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) + } + + resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) + } + + resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + } +` + + testConsulConfigEntryServiceRouterCE = ` resource "consul_config_entry" "web" { name = "web" kind = "service-defaults" @@ -56,19 +164,92 @@ resource "consul_config_entry" "admin_service_defaults" { Protocol = "http" }) } + resource "consul_config_entry_service_router" "foo" { name = consul_config_entry.web.name routes { - match { - http { - path_prefix = "/admin" - } - } - - destination { - service = consul_config_entry.admin_service_defaults.name - } - } + match { + http { + path_prefix = "/admin" + } + } + + destination { + service = consul_config_entry.admin_service_defaults.name + } + } +}` + + testConsulConfigEntryServiceRouterCE_noMatch = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) } -` + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + + routes { + destination { + service = consul_config_entry.admin_service_defaults.name + } + } +}` + + testConsulConfigEntryServiceRouterCE_noDestination = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + + routes { + match { + http { + path_prefix = "/admin" + } + } + } +}` +) diff --git a/consul/resource_consul_config_entry_service_splitter.go b/consul/resource_consul_config_entry_service_splitter.go index a953afe9..2cc8fccb 100644 --- a/consul/resource_consul_config_entry_service_splitter.go +++ b/consul/resource_consul_config_entry_service_splitter.go @@ -208,7 +208,7 @@ func (s *serviceSplitter) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, return configEntry, nil } -func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error { +func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error { sp, ok := ce.(*consulapi.ServiceSplitterConfigEntry) if !ok { return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceSplitter, ce.GetKind()) @@ -262,5 +262,5 @@ func (s *serviceSplitter) Write(ce consulapi.ConfigEntry, sw *stateWriter) error } sw.set("splits", splits) - return nil + return sw.error() } diff --git a/docs/resources/config_entry_service_defaults.md b/docs/resources/config_entry_service_defaults.md index 4265f0bd..ee7783cc 100644 --- a/docs/resources/config_entry_service_defaults.md +++ b/docs/resources/config_entry_service_defaults.md @@ -116,15 +116,9 @@ Optional: - `balance_outbound_connections` (String) Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads. - `connect_timeout_ms` (Number) -- `envoy_cluster_json` (String) -- `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--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)) -- `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--defaults--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. @@ -165,7 +159,6 @@ Optional: - `balance_outbound_connections` (String) Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads. - `connect_timeout_ms` (Number) -- `envoy_cluster_json` (String) - `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)) @@ -204,5 +197,3 @@ Optional: - `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. - - diff --git a/docs/resources/config_entry_service_intentions.md b/docs/resources/config_entry_service_intentions.md new file mode 100644 index 00000000..1da6c2bf --- /dev/null +++ b/docs/resources/config_entry_service_intentions.md @@ -0,0 +1,113 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_config_entry_service_intentions Resource - terraform-provider-consul" +subcategory: "" +description: |- + The consul_service_intentions_config_entry resource configures a service intentions https://developer.hashicorp.com/consul/docs/connect/config-entries/service-intentions that are configurations for controlling access between services in the service mesh. A single service intentions configuration entry specifies one destination service and one or more L4 traffic sources, L7 traffic sources, or combination of traffic sources. +--- + +# consul_config_entry_service_intentions (Resource) + +The `consul_service_intentions_config_entry` resource configures a [service intentions](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-intentions) that are configurations for controlling access between services in the service mesh. A single service intentions configuration entry specifies one destination service and one or more L4 traffic sources, L7 traffic sources, or combination of traffic sources. + + + + +## Schema + +### Required + +- `name` (String) Specifies a name of the destination service for all intentions defined in the configuration entry. + +### Optional + +- `jwt` (Block Set) Specifies a JSON Web Token provider configured in a JWT provider configuration entry, as well as additional configurations for verifying a service's JWT before authorizing communication between services (see [below for nested schema](#nestedblock--jwt)) +- `meta` (Map of String) Specifies key-value pairs to add to the KV store. +- `namespace` (String) Specifies the namespace to apply the configuration entry. +- `partition` (String) Specifies the admin partition to apply the configuration entry. +- `sources` (Block List) List of configurations that define intention sources and the authorization granted to the sources. (see [below for nested schema](#nestedblock--sources)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `jwt` + +Optional: + +- `providers` (Block List) Specifies the names of one or more previously configured JWT provider configuration entries, which include the information necessary to validate a JSON web token. (see [below for nested schema](#nestedblock--jwt--providers)) + + +### Nested Schema for `jwt.providers` + +Optional: + +- `name` (String) Specifies the name of a JWT provider defined in the Name field of the jwt-provider configuration entry. +- `verify_claims` (Block List) Specifies additional token information to verify beyond what is configured in the JWT provider configuration entry. (see [below for nested schema](#nestedblock--jwt--providers--verify_claims)) + + +### Nested Schema for `jwt.providers.verify_claims` + +Optional: + +- `path` (List of String) Specifies the path to the claim in the JSON web token. +- `value` (String) Specifies the value to match on when verifying the the claim designated in path. + + + + + +### Nested Schema for `sources` + +Optional: + +- `action` (String) Specifies the action to take when the source sends traffic to the destination service. +- `description` (String) Specifies a description of the intention. +- `legacy_create_time` (String) Read-only timestamp for the intention creation. +- `legacy_id` (String) Read-only unique user ID (UUID) for the intention in the system. +- `legacy_meta` (Map of String) Read-only set of arbitrary key-value pairs to attach to the intention. +- `legacy_update_time` (String) Read-only timestamp marking the most recent intention update. +- `name` (String) Specifies the name of the source that the intention allows or denies traffic from. +- `namespace` (String) Specifies the traffic source namespace that the intention allows or denies traffic from. +- `partition` (String) Specifies the name of an admin partition that the intention allows or denies traffic from. +- `peer` (String) Specifies the name of a peered Consul cluster that the intention allows or denies traffic from +- `permissions` (Block List) Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action. (see [below for nested schema](#nestedblock--sources--permissions)) +- `precedence` (Number) The Precedence field contains a read-only integer. Consul generates the value based on name configurations for the source and destination services. +- `sameness_group` (String) Specifies the name of a sameness group that the intention allows or denies traffic from. +- `type` (String) Specifies the type of destination service that the configuration entry applies to. + + +### Nested Schema for `sources.permissions` + +Required: + +- `action` (String) Specifies the action to take when the source sends traffic to the destination service. The value is either allow or deny. +- `http` (Block Set, Min: 1) Specifies a set of HTTP-specific match criteria. (see [below for nested schema](#nestedblock--sources--permissions--http)) + + +### Nested Schema for `sources.permissions.http` + +Optional: + +- `headers` (Block List) Specifies a header name and matching criteria for HTTP request headers. (see [below for nested schema](#nestedblock--sources--permissions--http--headers)) +- `methods` (List of String) Specifies a list of HTTP methods. +- `path_exact` (String) Specifies an exact path to match on the HTTP request path. +- `path_prefix` (String) Specifies a path prefix to match on the HTTP request path. +- `path_regex` (String) Defines a regular expression to match on the HTTP request path. + + +### Nested Schema for `sources.permissions.http.headers` + +Required: + +- `name` (String) Specifies the name of the header to match. + +Optional: + +- `exact` (String) Specifies a value for the header key set in the Name field. If the request header value matches the Exact value, Consul applies the permission. +- `invert` (Boolean) Inverts the matching logic configured in the Header. +- `prefix` (String) Specifies a prefix value for the header key set in the Name field. +- `present` (Boolean) Enables a match if the header configured in the Name field appears in the request. Consul matches on any value as long as the header key appears in the request. +- `regex` (String) Specifies a regular expression pattern as the value for the header key set in the Name field. +- `suffix` (String) Specifies a suffix value for the header key set in the Name field. diff --git a/docs/resources/config_entry_service_resolver.md b/docs/resources/config_entry_service_resolver.md new file mode 100644 index 00000000..86985bc5 --- /dev/null +++ b/docs/resources/config_entry_service_resolver.md @@ -0,0 +1,140 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_config_entry_service_resolver Resource - terraform-provider-consul" +subcategory: "" +description: |- + The consul_config_entry_service_resolver resource configures a service resolver https://developer.hashicorp.com/consul/docs/connect/config-entries/service-resolver that creates named subsets of service instances and define their behavior when satisfying upstream requests. +--- + +# consul_config_entry_service_resolver (Resource) + +The `consul_config_entry_service_resolver` resource configures a [service resolver](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-resolver) that creates named subsets of service instances and define their behavior when satisfying upstream requests. + + + + +## Schema + +### Required + +- `name` (String) Specifies a name for the configuration entry. + +### Optional + +- `connect_timeout` (String) Specifies the timeout duration for establishing new network connections to this service. +- `default_subset` (String) Specifies a defined subset of service instances to use when no explicit subset is requested. If this parameter is not specified, Consul uses the unnamed default subset. +- `failover` (Block Set) Specifies controls for rerouting traffic to an alternate pool of service instances if the target service fails. (see [below for nested schema](#nestedblock--failover)) +- `load_balancer` (Block Set) Specifies the load balancing policy and configuration for services issuing requests to this upstream. (see [below for nested schema](#nestedblock--load_balancer)) +- `meta` (Map of String) Specifies key-value pairs to add to the KV store. +- `namespace` (String) Specifies the namespace that the service resolver applies to. +- `partition` (String) Specifies the admin partition that the service resolver applies to. +- `redirect` (Block Set) Specifies redirect instructions for local service traffic so that services deployed to a different network location resolve the upstream request instead. (see [below for nested schema](#nestedblock--redirect)) +- `request_timeout` (String) Specifies the timeout duration for receiving an HTTP response from this service. +- `subsets` (Block Set) Specifies names for custom service subsets and the conditions under which service instances belong to each subset. (see [below for nested schema](#nestedblock--subsets)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `failover` + +Required: + +- `subset_name` (String) Name of subset. + +Optional: + +- `datacenters` (List of String) Specifies an ordered list of datacenters at the failover location to attempt connections to during a failover scenario. When Consul cannot establish a connection with the first datacenter in the list, it proceeds sequentially until establishing a connection with another datacenter. +- `namespace` (String) Specifies the namespace at the failover location where the failover services are deployed. +- `sameness_group` (String) Specifies the sameness group at the failover location where the failover services are deployed. +- `service` (String) Specifies the name of the service to resolve at the failover location during a failover scenario. +- `service_subset` (String) Specifies the name of a subset of service instances to resolve at the failover location during a failover scenario. +- `targets` (Block List) Specifies a fixed list of failover targets to try during failover. This list can express complicated failover scenarios. (see [below for nested schema](#nestedblock--failover--targets)) + + +### Nested Schema for `failover.targets` + +Optional: + +- `datacenter` (String) Specifies the WAN federated datacenter to use for the failover target. If empty, the current datacenter is used. +- `namespace` (String) Specifies the namespace to use for the failover target. If empty, the default namespace is used. +- `partition` (String) Specifies the admin partition within the same datacenter to use for the failover target. If empty, the default partition is used. +- `peer` (String) Specifies the destination cluster peer to resolve the target service name from. +- `service` (String) Specifies the service name to use for the failover target. If empty, the current service name is used. +- `service_subset` (String) Specifies the named subset to use for the failover target. If empty, the default subset for the requested service name is used. + + + + +### Nested Schema for `load_balancer` + +Optional: + +- `hash_policies` (Block List) Specifies a list of hash policies to use for hashing load balancing algorithms. Consul evaluates hash policies individually and combines them so that identical lists result in the same hash. (see [below for nested schema](#nestedblock--load_balancer--hash_policies)) +- `least_request_config` (Block Set) Specifies configuration for the least_request policy type. (see [below for nested schema](#nestedblock--load_balancer--least_request_config)) +- `policy` (String) Specifies the type of load balancing policy for selecting a host. +- `ring_hash_config` (Block Set) Specifies configuration for the ring_hash policy type. (see [below for nested schema](#nestedblock--load_balancer--ring_hash_config)) + + +### Nested Schema for `load_balancer.hash_policies` + +Optional: + +- `cookie_config` (Block Set) Specifies additional configuration options for the cookie hash policy type. (see [below for nested schema](#nestedblock--load_balancer--hash_policies--cookie_config)) +- `field` (String) Specifies the attribute type to hash on. You cannot specify the Field parameter if SourceIP is also configured. +- `field_value` (String) Specifies the value to hash, such as a header name, cookie name, or a URL query parameter name. +- `source_ip` (Boolean) Determines if the hash type should be source IP address. +- `terminal` (Boolean) Determines if Consul should stop computing the hash when multiple hash policies are present. + + +### Nested Schema for `load_balancer.hash_policies.cookie_config` + +Optional: + +- `path` (String) Specifies the path to set for the cookie. +- `session` (Boolean) Directs Consul to generate a session cookie with no expiration. +- `ttl` (String) Specifies the TTL for generated cookies. Cannot be specified for session cookies. + + + + +### Nested Schema for `load_balancer.least_request_config` + +Optional: + +- `choice_count` (Number) + + + +### Nested Schema for `load_balancer.ring_hash_config` + +Optional: + +- `maximum_ring_size` (Number) Determines the maximum number of entries in the hash ring. +- `minimum_ring_size` (Number) Determines the minimum number of entries in the hash ring. + + + + +### Nested Schema for `redirect` + +Optional: + +- `datacenter` (String) Specifies the datacenter at the redirect’s destination that resolves local upstream requests. +- `namespace` (String) Specifies the namespace at the redirect’s destination that resolves local upstream requests. +- `partition` (String) Specifies the admin partition at the redirect’s destination that resolves local upstream requests. +- `peer` (String) Specifies the cluster with an active cluster peering connection at the redirect’s destination that resolves local upstream requests. +- `sameness_group` (String) Specifies the sameness group at the redirect’s destination that resolves local upstream requests. +- `service` (String) Specifies the name of a service at the redirect’s destination that resolves local upstream requests. +- `service_subset` (String) Specifies the name of a subset of services at the redirect’s destination that resolves local upstream requests. If empty, the default subset is used. If specified, you must also specify at least one of the following in the same Redirect map: Service, Namespace, andDatacenter. + + + +### Nested Schema for `subsets` + +Required: + +- `filter` (String) Specifies an expression that filters the DNS elements of service instances that belong to the subset. If empty, all healthy instances of a service are returned. +- `name` (String) Name of subset. +- `only_passing` (Boolean) Determines if instances that return a warning from a health check are allowed to resolve a request. When set to false, instances with passing and warning states are considered healthy. When set to true, only instances with a passing health check state are considered healthy. diff --git a/docs/resources/config_entry_service_router.md b/docs/resources/config_entry_service_router.md new file mode 100644 index 00000000..ff4738e8 --- /dev/null +++ b/docs/resources/config_entry_service_router.md @@ -0,0 +1,122 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_config_entry_service_router Resource - terraform-provider-consul" +subcategory: "" +description: |- + The consul_config_entry_service_router resource configures a service router https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router to redirect a traffic request for a service to one or more specific service instances. +--- + +# consul_config_entry_service_router (Resource) + +The `consul_config_entry_service_router` resource configures a [service router](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router) to redirect a traffic request for a service to one or more specific service instances. + + + + +## Schema + +### Required + +- `name` (String) Specifies a name for the configuration entry. + +### Optional + +- `meta` (Map of String) Specifies key-value pairs to add to the KV store. +- `namespace` (String) Specifies the namespace to apply the configuration entry. +- `partition` (String) Specifies the admin partition to apply the configuration entry. +- `routes` (Block List) Defines the possible routes for L7 requests. (see [below for nested schema](#nestedblock--routes)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `routes` + +Optional: + +- `destination` (Block List, Max: 1) Specifies the target service to route matching requests to, as well as behavior for the request to follow when routed. (see [below for nested schema](#nestedblock--routes--destination)) +- `match` (Block List, Max: 1) Describes a set of criteria that Consul compares incoming L7 traffic with. (see [below for nested schema](#nestedblock--routes--match)) + + +### Nested Schema for `routes.destination` + +Optional: + +- `idle_timeout` (String) Specifies the total amount of time permitted for the request stream to be idle. +- `namespace` (String) Specifies the Consul namespace to resolve the service from instead of the current namespace. +- `num_retries` (Number) Specifies the number of times to retry the request when a retry condition occurs. +- `partition` (String) Specifies the Consul admin partition to resolve the service from instead of the current partition. +- `prefix_rewrite` (String) Specifies rewrites to the HTTP request path before proxying it to its final destination. +- `request_headers` (Block List, Max: 1) Specifies a set of HTTP-specific header modification rules applied to requests routed with the service router. (see [below for nested schema](#nestedblock--routes--destination--request_headers)) +- `request_timeout` (String) Specifies the total amount of time permitted for the entire downstream request to be processed, including retry attempts. +- `response_headers` (Block List, Max: 1) Specifies a set of HTTP-specific header modification rules applied to responses routed with the service router. (see [below for nested schema](#nestedblock--routes--destination--response_headers)) +- `retry_on` (List of String) Specifies a list of conditions for Consul to retry requests based on the response from an upstream service. +- `retry_on_connect_failure` (Boolean) Specifies that connection failure errors that trigger a retry request. +- `retry_on_status_codes` (List of Number) Specifies a list of integers for HTTP response status codes that trigger a retry request. +- `service` (String) Specifies the name of the service to resolve. +- `service_subset` (String) Specifies a named subset of the given service to resolve instead of the one defined as that service's `default_subset` in the service resolver configuration entry. + + +### Nested Schema for `routes.destination.request_headers` + +Optional: + +- `add` (Map of String) Defines a set of key-value pairs to add to the header. Use header names as the keys. +- `remove` (List of String) Defines a list of headers to remove. +- `set` (Map of String) Defines a set of key-value pairs to add to the request header or to replace existing header values with. + + + +### Nested Schema for `routes.destination.response_headers` + +Optional: + +- `add` (Map of String) Defines a set of key-value pairs to add to the header. Use header names as the keys +- `remove` (List of String) Defines a list of headers to remove. +- `set` (Map of String) Defines a set of key-value pairs to add to the response header or to replace existing header values with + + + + +### Nested Schema for `routes.match` + +Optional: + +- `http` (Block List, Max: 1) Specifies a set of HTTP criteria used to evaluate incoming L7 traffic for matches. (see [below for nested schema](#nestedblock--routes--match--http)) + + +### Nested Schema for `routes.match.http` + +Optional: + +- `header` (Block List) Specifies information in the HTTP request header to match with. (see [below for nested schema](#nestedblock--routes--match--http--header)) +- `methods` (List of String) Specifies HTTP methods that the match applies to. +- `path_exact` (String) Specifies the exact path to match on the HTTP request path. +- `path_prefix` (String) Specifies the path prefix to match on the HTTP request path. +- `path_regex` (String) Specifies a regular expression to match on the HTTP request path. +- `query_param` (Block List) Specifies information to match to on HTTP query parameters. (see [below for nested schema](#nestedblock--routes--match--http--query_param)) + + +### Nested Schema for `routes.match.http.header` + +Optional: + +- `exact` (String) Specifies that a request matches when the header with the given name is this exact value. +- `invert` (Boolean) Specifies that the logic for the HTTP header match should be inverted. +- `name` (String) Specifies the name of the HTTP header to match. +- `prefix` (String) Specifies that a request matches when the header with the given name has this prefix. +- `present` (Boolean) Specifies that a request matches when the value in the `name` argument is present anywhere in the HTTP header. +- `regex` (String) Specifies that a request matches when the header with the given name matches this regular expression. +- `suffix` (String) Specifies that a request matches when the header with the given name has this suffix. + + + +### Nested Schema for `routes.match.http.query_param` + +Optional: + +- `exact` (String) Specifies that a request matches when the query parameter with the given name is this exact value. +- `name` (String) Specifies the name of the HTTP query parameter to match. +- `present` (Boolean) Specifies that a request matches when the value in the `name` argument is present anywhere in the HTTP query parameter. +- `regex` (String) Specifies that a request matches when the query parameter with the given name matches this regular expression. diff --git a/docs/resources/config_entry_service_splitter.md b/docs/resources/config_entry_service_splitter.md index b5a94d19..f5da430a 100644 --- a/docs/resources/config_entry_service_splitter.md +++ b/docs/resources/config_entry_service_splitter.md @@ -64,5 +64,3 @@ Optional: - `add` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the header. Use header names as the keys. Header names are not case-sensitive. If header values with the same name already exist, the value is appended and Consul applies both headers. - `remove` (List of String) Defines an list of headers to remove. Consul removes only headers containing exact matches. Header names are not case-sensitive. - `set` (Map of String) Map of one or more key-value pairs. Defines a set of key-value pairs to add to the request header or to replace existing header values with. Use header names as the keys. Header names are not case-sensitive. If header values with the same names already exist, Consul replaces the header values. - - From 65c97db5f153ef09c1c84b573bbb98197f6f1af1 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 9 Oct 2023 12:32:01 +0530 Subject: [PATCH 85/89] service router ee test --- ...sul_config_entry_service_router_ee_test.go | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 consul/resource_consul_config_entry_service_router_ee_test.go diff --git a/consul/resource_consul_config_entry_service_router_ee_test.go b/consul/resource_consul_config_entry_service_router_ee_test.go new file mode 100644 index 00000000..9f753746 --- /dev/null +++ b/consul/resource_consul_config_entry_service_router_ee_test.go @@ -0,0 +1,261 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccConsulConfigEntryServiceRouterEETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceRouterEE_Empty, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "0"), + ), + }, + { + Config: testConsulConfigEntryServiceRouterEE, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", "ns1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", "pr1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.idle_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.num_retries", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.prefix_rewrite", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.response_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_connect_failure", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_status_codes.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service", "admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service_subset", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.header.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.methods.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_exact", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_prefix", "/admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_regex", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.query_param.#", "0"), + ), + }, + { + Config: testConsulConfigEntryServiceRouterEE_noMatch, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", "ns1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", "pr1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.idle_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.num_retries", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.prefix_rewrite", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.request_timeout", "0s"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.response_headers.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_connect_failure", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.retry_on_status_codes.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service", "admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.0.service_subset", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "0"), + ), + }, + { + Config: testConsulConfigEntryServiceRouterEE_noDestination, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "id", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "meta.%", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "name", "web"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "namespace", "ns1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "partition", "pr1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.destination.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.header.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.methods.#", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_exact", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_prefix", "/admin"), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.path_regex", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_router.foo", "routes.0.match.0.http.0.query_param.#", "0"), + ), + }, + }, + }) +} + +const ( + testConsulConfigEntryServiceRouterEE_Empty = ` + resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) + } + + resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) + } + + resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + } +` + + testConsulConfigEntryServiceRouterEE = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + namespace = "ns1" + partition = "pr1" + + routes { + match { + http { + path_prefix = "/admin" + } + } + + destination { + service = consul_config_entry.admin_service_defaults.name + } + } +}` + + testConsulConfigEntryServiceRouterEE_noMatch = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + namespace = "ns1" + partition = "pr1" + + routes { + destination { + service = consul_config_entry.admin_service_defaults.name + } + } +}` + + testConsulConfigEntryServiceRouterEE_noDestination = ` +resource "consul_config_entry" "web" { + name = "web" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry" "admin_service_defaults" { + name = "admin" + kind = "service-defaults" + + config_json = jsonencode({ + Expose = {} + MeshGateway = {} + TransparentProxy = {} + Protocol = "http" + }) +} + +resource "consul_config_entry_service_router" "foo" { + name = consul_config_entry.web.name + namespace = "ns1" + partition = "pr1" + + routes { + match { + http { + path_prefix = "/admin" + } + } + } +}` +) From d05516b9c52dbed85ca41615d81b771a0dbb912b Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 9 Oct 2023 12:41:11 +0530 Subject: [PATCH 86/89] fix intentnios --- consul/resource_consul_config_entry_service_intentions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index e769323f..39fa0ff4 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -539,6 +539,7 @@ func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, d *schema.ResourceDa permissions = append(permissions, permissionMap) } sourceMap["permissions"] = permissions + sources = append(sources, sourceMap) } sw.set("sources", sources) From d323696826b371c098ba606a9f2cb52d0a829304 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 9 Oct 2023 17:19:59 +0530 Subject: [PATCH 87/89] make intentinos tests passing --- consul/resource_consul_config_entry_service_intentions.go | 2 +- .../resource_consul_config_entry_service_intentions_ce_test.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/consul/resource_consul_config_entry_service_intentions.go b/consul/resource_consul_config_entry_service_intentions.go index 39fa0ff4..213495f0 100644 --- a/consul/resource_consul_config_entry_service_intentions.go +++ b/consul/resource_consul_config_entry_service_intentions.go @@ -478,7 +478,6 @@ func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, d *schema.ResourceDa for _, jwtProvider := range si.JWT.Providers { jwtProviderMap := make(map[string]interface{}) jwtProviderMap["name"] = jwtProvider.Name - jwtProviderMap["verify_claims"] = make([]map[string]interface{}, 0) verifyClaims := make([]map[string]interface{}, 0) for _, vc := range jwtProvider.VerifyClaims { vcMap := make(map[string]interface{}) @@ -490,6 +489,7 @@ func (s *serviceIntentions) Write(ce consulapi.ConfigEntry, d *schema.ResourceDa vcMap["value"] = vc.Value verifyClaims = append(verifyClaims, vcMap) } + jwtProviderMap["verify_claims"] = verifyClaims jwtProviders = append(jwtProviders, jwtProviderMap) } jwt[0]["providers"] = jwtProviders diff --git a/consul/resource_consul_config_entry_service_intentions_ce_test.go b/consul/resource_consul_config_entry_service_intentions_ce_test.go index a8cb33c6..a7b515f7 100644 --- a/consul/resource_consul_config_entry_service_intentions_ce_test.go +++ b/consul/resource_consul_config_entry_service_intentions_ce_test.go @@ -32,6 +32,7 @@ resource "consul_config_entry" "jwt_provider" { kind = "jwt-provider" config_json = jsonencode({ + ClockSkewSeconds = 30 Issuer = "test-issuer" JSONWebKeySet = { Remote = { From 0e691fbfece12e5e26a59e10313e5217c6692e29 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 9 Oct 2023 17:30:27 +0530 Subject: [PATCH 88/89] update tests --- ...config_entry_service_intentions_ce_test.go | 18 +++- ...config_entry_service_intentions_ee_test.go | 92 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 consul/resource_consul_config_entry_service_intentions_ee_test.go diff --git a/consul/resource_consul_config_entry_service_intentions_ce_test.go b/consul/resource_consul_config_entry_service_intentions_ce_test.go index a7b515f7..25d8a806 100644 --- a/consul/resource_consul_config_entry_service_intentions_ce_test.go +++ b/consul/resource_consul_config_entry_service_intentions_ce_test.go @@ -4,9 +4,8 @@ package consul import ( - "testing" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" ) func TestAccConsulConfigEntryServiceIntentionsCETest(t *testing.T) { @@ -20,6 +19,21 @@ func TestAccConsulConfigEntryServiceIntentionsCETest(t *testing.T) { Config: testConsulConfigEntryServiceIntentionsCE, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "name", "service-intention"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "namespace", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "partition", ""), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.name", "frontend-webapp"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.type", "consul"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.action", "allow"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.precedence", "9"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.name", "nightly-cronjob"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.type", "consul"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.action", "deny"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.precedence", "9"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.name", "okta"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.0.path.0", "/"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.0.path.1", "path1"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.1.path.0", "/path"), ), }, }, diff --git a/consul/resource_consul_config_entry_service_intentions_ee_test.go b/consul/resource_consul_config_entry_service_intentions_ee_test.go new file mode 100644 index 00000000..8203132f --- /dev/null +++ b/consul/resource_consul_config_entry_service_intentions_ee_test.go @@ -0,0 +1,92 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulConfigEntryServiceIntentionsEETest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulConfigEntryServiceIntentionsEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "name", "service-intention"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "namespace", "ns1"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "partition", "pr1"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.name", "frontend-webapp"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.type", "consul"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.action", "allow"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.0.precedence", "9"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.name", "nightly-cronjob"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.type", "consul"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.action", "deny"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "sources.1.precedence", "9"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.name", "okta"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.0.path.0", "/"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.0.path.1", "path1"), + resource.TestCheckResourceAttr("consul_config_entry_service_intentions.foo", "jwt.2394986741.providers.0.verify_claims.1.path.0", "/path"), + ), + }, + }, + }) +} + +const testConsulConfigEntryServiceIntentionsEE = ` +resource "consul_config_entry" "jwt_provider" { + name = "okta" + kind = "jwt-provider" + + config_json = jsonencode({ + ClockSkewSeconds = 30 + Issuer = "test-issuer" + JSONWebKeySet = { + Remote = { + URI = "https://127.0.0.1:9091" + FetchAsynchronously = true + } + } + }) +} +resource "consul_config_entry_service_intentions" "foo" { + name = "service-intention" + namespace = "ns1" + partition = "pr1" + meta = { + key = "value" + } + jwt { + providers { + name = consul_config_entry.jwt_provider.name + verify_claims { + path = ["/", "path1"] + value = "" + } + verify_claims { + path = ["/path"] + value = "value" + } + } + } + sources { + action = "allow" + name = "frontend-webapp" + precedence = 9 + type = "consul" + } + sources { + name = "nightly-cronjob" + precedence = 9 + type = "consul" + action = "deny" + } +} +` From ca0423333fc973bac547559063a8f3abca995692 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Mon, 9 Oct 2023 17:31:27 +0530 Subject: [PATCH 89/89] fix tests --- .../resource_consul_config_entry_service_defaults_ee_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consul/resource_consul_config_entry_service_defaults_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go index 9d4032f9..a5949cfc 100644 --- a/consul/resource_consul_config_entry_service_defaults_ee_test.go +++ b/consul/resource_consul_config_entry_service_defaults_ee_test.go @@ -8,11 +8,11 @@ import ( "testing" ) -func TestAccConsulServiceDefaultsConfiEEEntryTest(t *testing.T) { +func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { providers, _ := startTestServer(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, Providers: providers, Steps: []resource.TestStep{ {