From 584ad89e41d39307f5601e21af608711c86d2f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Wed, 12 May 2021 17:36:12 +0200 Subject: [PATCH] Fix the way datacenter, token and namespace are inherited from the provider configuration (#259) This also adds test with multiple datacenters, we were not testing this configuration until now. The tests are not run by default to not make local development more complicated but are run in CI both with Consul Community Edition and Consul Enterprise. Closes https://github.com/hashicorp/terraform-provider-consul/issues/8 --- .travis.yml | 28 +++++ README.md | 11 ++ consul/data_source_consul_acl_auth_method.go | 11 +- consul/data_source_consul_acl_policy.go | 10 +- consul/data_source_consul_acl_role.go | 11 +- consul/data_source_consul_acl_token.go | 7 +- .../data_source_consul_acl_token_secret_id.go | 7 +- consul/data_source_consul_agent_config.go | 3 +- consul/data_source_consul_agent_self.go | 3 +- consul/data_source_consul_autopilot_health.go | 47 ++++---- consul/data_source_consul_key_prefix.go | 14 +-- consul/data_source_consul_key_prefix_test.go | 36 +++++++ consul/data_source_consul_keys.go | 13 +-- consul/data_source_consul_keys_test.go | 44 ++++++++ ...data_source_consul_network_area_members.go | 13 +-- ...source_consul_network_area_members_test.go | 28 +++++ consul/data_source_consul_network_segments.go | 15 +-- ...ata_source_consul_network_segments_test.go | 22 ++++ consul/data_source_consul_nodes.go | 70 ++++-------- consul/data_source_consul_nodes_test.go | 30 ++++++ consul/data_source_consul_service.go | 16 ++- consul/data_source_consul_service_health.go | 25 ++--- .../data_source_consul_service_health_test.go | 20 ++++ consul/data_source_consul_services.go | 41 +++---- consul/data_source_consul_services_test.go | 38 ++++++- consul/key_client.go | 16 +-- consul/query_options.go | 69 +++++------- consul/resource_consul_acl_auth_method.go | 26 ++--- .../resource_consul_acl_auth_method_test.go | 4 +- consul/resource_consul_acl_binding_rule.go | 25 ++--- .../resource_consul_acl_binding_rule_test.go | 2 +- consul/resource_consul_acl_policy.go | 22 ++-- consul/resource_consul_acl_policy_test.go | 2 +- consul/resource_consul_acl_role.go | 22 ++-- consul/resource_consul_acl_role_test.go | 2 +- consul/resource_consul_acl_token.go | 24 +---- ...urce_consul_acl_token_policy_attachment.go | 14 +-- ...consul_acl_token_policy_attachment_test.go | 4 +- ...source_consul_acl_token_role_attachment.go | 16 +-- ...e_consul_acl_token_role_attachment_test.go | 4 +- consul/resource_consul_acl_token_test.go | 2 +- consul/resource_consul_agent_service.go | 6 +- consul/resource_consul_agent_service_test.go | 4 +- consul/resource_consul_autopilot_config.go | 34 ++---- .../resource_consul_autopilot_config_test.go | 49 ++++++++- consul/resource_consul_catalog_entry.go | 78 +++----------- consul/resource_consul_catalog_entry_test.go | 6 +- .../resource_consul_certificate_authority.go | 8 +- consul/resource_consul_config_entry.go | 23 ++-- consul/resource_consul_intention.go | 54 +++------- consul/resource_consul_intention_test.go | 4 +- consul/resource_consul_key_prefix.go | 52 ++------- consul/resource_consul_key_prefix_test.go | 48 +++++++-- consul/resource_consul_keys.go | 60 +---------- consul/resource_consul_keys_test.go | 81 ++++++++++---- consul/resource_consul_license.go | 37 +------ consul/resource_consul_license_test.go | 26 ----- consul/resource_consul_namespace.go | 20 ++-- consul/resource_consul_network_area.go | 50 +-------- consul/resource_consul_network_area_test.go | 71 +++++++++++- consul/resource_consul_node.go | 72 +++---------- consul/resource_consul_node_test.go | 61 +++++++++-- consul/resource_consul_prepared_query.go | 34 ++---- consul/resource_consul_prepared_query_test.go | 65 +++++++++-- consul/resource_consul_service.go | 101 +++++------------- consul/resource_consul_service_test.go | 61 ++++++++++- consul/resource_provider.go | 47 ++++++-- consul/resource_provider_test.go | 38 ++++++- consul_test.hcl | 3 + consul_test_dc2.hcl | 26 +++++ 70 files changed, 1062 insertions(+), 974 deletions(-) create mode 100644 consul_test_dc2.hcl diff --git a/.travis.yml b/.travis.yml index 66daef3f..c051c123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,34 @@ script: docker.mirror.hashicorp.services/hashicorp/consul-enterprise:latest consul agent -dev -config-file consul_test.hcl -client=0.0.0.0 - make testacc TESTARGS="-count=1" - docker stop consul-test +- docker run --rm + -d + --name consul-test-dc2 + -v $PWD/consul_test_dc2.hcl:/consul_test_dc2.hcl:ro + --net host + docker.mirror.hashicorp.services/consul:latest consul agent -dev -config-file consul_test_dc2.hcl +- docker run --rm + -d + --name consul-test + -v $PWD/consul_test.hcl:/consul_test.hcl:ro + --net host + docker.mirror.hashicorp.services/consul:latest consul agent -dev -config-file consul_test.hcl +- TEST_REMOTE_DATACENTER=1 make testacc TESTARGS="-count=1" +- docker stop consul-test consul-test-dc2 +- docker run --rm + -d + --name consul-test-dc2 + -v $PWD/consul_test_dc2.hcl:/consul_test_dc2.hcl:ro + --net host + docker.mirror.hashicorp.services/hashicorp/consul-enterprise:latest consul agent -dev -config-file consul_test_dc2.hcl +- docker run --rm + -d + --name consul-test + -v $PWD/consul_test.hcl:/consul_test.hcl:ro + --net host + docker.mirror.hashicorp.services/hashicorp/consul-enterprise:latest consul agent -dev -config-file consul_test.hcl +- TEST_REMOTE_DATACENTER=1 make testacc TESTARGS="-count=1" +- docker stop consul-test consul-test-dc2 - make vet branches: diff --git a/README.md b/README.md index 32bae13a..4cc1bd95 100644 --- a/README.md +++ b/README.md @@ -114,3 +114,14 @@ locally and then run it in development mode: ``` $ consul agent -dev ``` + +It is also possible to run additional tests to test the provider with multiple +datacenters: + +```sh +$ consul agent -dev -config-file ./consul_test_dc2.hcl & +$ consul agent -dev -config-file ./consul_test.hcl & +$ export CONSUL_HTTP_ADDR=localhost:8500 +$ export CONSUL_HTTP_TOKEN=master-token +$ TEST_REMOTE_DATACENTER=1 make testacc +``` diff --git a/consul/data_source_consul_acl_auth_method.go b/consul/data_source_consul_acl_auth_method.go index c0eb6958..1ea0d1c4 100644 --- a/consul/data_source_consul_acl_auth_method.go +++ b/consul/data_source_consul_acl_auth_method.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -86,16 +85,8 @@ func dataSourceConsulACLAuthMethod() *schema.Resource { } func dataSourceConsulACLAuthMethodRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) name := d.Get("name").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - qOpts := &consulapi.QueryOptions{ - Datacenter: dc, - Namespace: getNamespace(d, meta), - } authMethod, _, err := client.ACL().AuthMethodRead(name, qOpts) if err != nil { diff --git a/consul/data_source_consul_acl_policy.go b/consul/data_source_consul_acl_policy.go index 884f27b3..e5a76846 100644 --- a/consul/data_source_consul_acl_policy.go +++ b/consul/data_source_consul_acl_policy.go @@ -41,16 +41,8 @@ func dataSourceConsulACLPolicy() *schema.Resource { } func dataSourceConsulACLPolicyRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) name := d.Get("name").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - qOpts := &consulapi.QueryOptions{ - Datacenter: dc, - Namespace: getNamespace(d, meta), - } var policyEntry *consulapi.ACLPolicyListEntry policyEntries, _, err := client.ACL().PolicyList(qOpts) diff --git a/consul/data_source_consul_acl_role.go b/consul/data_source_consul_acl_role.go index 57c41a0b..b8a4b625 100644 --- a/consul/data_source_consul_acl_role.go +++ b/consul/data_source_consul_acl_role.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -69,16 +68,8 @@ func dataSourceConsulACLRole() *schema.Resource { } func datasourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) name := d.Get("name").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - qOpts := &consulapi.QueryOptions{ - Datacenter: dc, - Namespace: getNamespace(d, meta), - } role, _, err := client.ACL().RoleReadByName(name, qOpts) if err != nil { diff --git a/consul/data_source_consul_acl_token.go b/consul/data_source_consul_acl_token.go index 5679cdb6..ef2b63e0 100644 --- a/consul/data_source_consul_acl_token.go +++ b/consul/data_source_consul_acl_token.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -56,11 +55,9 @@ func dataSourceConsulACLToken() *schema.Resource { } func dataSourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) accessorID := d.Get("accessor_id").(string) - qOpts := &consulapi.QueryOptions{ - Namespace: getNamespace(d, meta), - } + aclToken, _, err := client.ACL().TokenRead(accessorID, qOpts) if err != nil { return err diff --git a/consul/data_source_consul_acl_token_secret_id.go b/consul/data_source_consul_acl_token_secret_id.go index 53a95b21..4ed07b29 100644 --- a/consul/data_source_consul_acl_token_secret_id.go +++ b/consul/data_source_consul_acl_token_secret_id.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/encryption" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -47,11 +46,9 @@ func dataSourceConsulACLTokenSecretID() *schema.Resource { } func dataSourceConsulACLTokenSecretIDRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) accessorID := d.Get("accessor_id").(string) - qOpts := &consulapi.QueryOptions{ - Namespace: getNamespace(d, meta), - } + aclToken, _, err := client.ACL().TokenRead(accessorID, qOpts) if err != nil { return err diff --git a/consul/data_source_consul_agent_config.go b/consul/data_source_consul_agent_config.go index 5a5696c8..f4908810 100644 --- a/consul/data_source_consul_agent_config.go +++ b/consul/data_source_consul_agent_config.go @@ -51,7 +51,8 @@ func dataSourceConsulAgentConfig() *schema.Resource { } func dataSourceConsulAgentConfigRead(d *schema.ResourceData, meta interface{}) error { - agentSelf, err := getClient(meta).Agent().Self() + client, _, _ := getClient(d, meta) + agentSelf, err := client.Agent().Self() if err != nil { return err } diff --git a/consul/data_source_consul_agent_self.go b/consul/data_source_consul_agent_self.go index 411e43fa..d4337e60 100644 --- a/consul/data_source_consul_agent_self.go +++ b/consul/data_source_consul_agent_self.go @@ -503,7 +503,8 @@ func dataSourceConsulAgentSelf() *schema.Resource { } func dataSourceConsulAgentSelfRead(d *schema.ResourceData, meta interface{}) error { - info, err := getClient(meta).Agent().Self() + client, _, _ := getClient(d, meta) + info, err := client.Agent().Self() if err != nil { return err } diff --git a/consul/data_source_consul_autopilot_health.go b/consul/data_source_consul_autopilot_health.go index 0b63c47d..7463be89 100644 --- a/consul/data_source_consul_autopilot_health.go +++ b/consul/data_source_consul_autopilot_health.go @@ -12,70 +12,70 @@ func dataSourceConsulAutopilotHealth() *schema.Resource { Read: dataSourceConsulAutopilotHealthRead, Schema: map[string]*schema.Schema{ // Filters - "datacenter": &schema.Schema{ + "datacenter": { Optional: true, Type: schema.TypeString, }, // Out parameters - "healthy": &schema.Schema{ + "healthy": { Computed: true, Type: schema.TypeBool, }, - "failure_tolerance": &schema.Schema{ + "failure_tolerance": { Computed: true, Type: schema.TypeInt, }, - "servers": &schema.Schema{ + "servers": { Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "id": &schema.Schema{ + "id": { Computed: true, Type: schema.TypeString, }, - "name": &schema.Schema{ + "name": { Computed: true, Type: schema.TypeString, }, - "address": &schema.Schema{ + "address": { Computed: true, Type: schema.TypeString, }, - "serf_status": &schema.Schema{ + "serf_status": { Computed: true, Type: schema.TypeString, }, - "version": &schema.Schema{ + "version": { Computed: true, Type: schema.TypeString, }, - "leader": &schema.Schema{ + "leader": { Computed: true, Type: schema.TypeBool, }, - "last_contact": &schema.Schema{ + "last_contact": { Computed: true, Type: schema.TypeString, }, - "last_term": &schema.Schema{ + "last_term": { Computed: true, Type: schema.TypeInt, }, - "last_index": &schema.Schema{ + "last_index": { Computed: true, Type: schema.TypeInt, }, - "healthy": &schema.Schema{ + "healthy": { Computed: true, Type: schema.TypeBool, }, - "voter": &schema.Schema{ + "voter": { Computed: true, Type: schema.TypeBool, }, - "stable_since": &schema.Schema{ + "stable_since": { Computed: true, Type: schema.TypeString, }, @@ -87,23 +87,16 @@ func dataSourceConsulAutopilotHealth() *schema.Resource { } func dataSourceConsulAutopilotHealthRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() + getQueryOpts(qOpts, d, meta) - queryOpts, err := getQueryOpts(d, client, meta) - if err != nil { - return err - } - if datacenter, ok := d.GetOk("datacenter"); ok { - queryOpts.Datacenter = datacenter.(string) - } - - health, err := operator.AutopilotServerHealth(queryOpts) + health, err := operator.AutopilotServerHealth(qOpts) if err != nil { return err } const idKeyFmt = "autopilot-health-%s" - d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) + d.SetId(fmt.Sprintf(idKeyFmt, qOpts.Datacenter)) d.Set("healthy", health.Healthy) d.Set("failure_tolerance", health.FailureTolerance) diff --git a/consul/data_source_consul_key_prefix.go b/consul/data_source_consul_key_prefix.go index 3d1ec984..9081ab72 100644 --- a/consul/data_source_consul_key_prefix.go +++ b/consul/data_source_consul_key_prefix.go @@ -74,17 +74,7 @@ func dataSourceConsulKeyPrefix() *schema.Resource { } func dataSourceConsulKeyPrefixRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) pathPrefix := d.Get("path_prefix").(string) @@ -126,7 +116,7 @@ func dataSourceConsulKeyPrefixRead(d *schema.ResourceData, meta interface{}) err // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) d.Set("path_prefix", pathPrefix) d.SetId("-") diff --git a/consul/data_source_consul_key_prefix_test.go b/consul/data_source_consul_key_prefix_test.go index d2251842..33133161 100644 --- a/consul/data_source_consul_key_prefix_test.go +++ b/consul/data_source_consul_key_prefix_test.go @@ -59,6 +59,22 @@ func TestAccDataConsulKeyPrefix_namespaceEE(t *testing.T) { }) } +func TestAccDataConsulKeyPrefix_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccDataConsulKeyPrefixConfigDatacenter, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsulKeyPrefixAttribute("data.consul_key_prefix.dc1", "subkeys.%", "0"), + testAccCheckConsulKeyPrefixAttribute("data.consul_key_prefix.dc2", "subkeys.%", "1"), + ), + }, + }, + }) +} + func testAccCheckConsulKeyPrefixAttribute(n, attr, val string) resource.TestCheckFunc { return func(s *terraform.State) error { rn, ok := s.RootModule().Resources[n] @@ -146,3 +162,23 @@ data "consul_key_prefix" "read" { namespace = "test-key-prefix" } ` + +const testAccDataConsulKeyPrefixConfigDatacenter = ` +resource "consul_key_prefix" "dc2" { + datacenter = "dc2" + path_prefix = "test/" + + subkeys = { + "dc" = "dc2" + } +} + +data "consul_key_prefix" "dc1" { + path_prefix = consul_key_prefix.dc2.path_prefix +} + +data "consul_key_prefix" "dc2" { + datacenter = "dc2" + path_prefix = consul_key_prefix.dc2.path_prefix +} +` diff --git a/consul/data_source_consul_keys.go b/consul/data_source_consul_keys.go index c229150c..2fb1b8ca 100644 --- a/consul/data_source_consul_keys.go +++ b/consul/data_source_consul_keys.go @@ -61,16 +61,7 @@ func dataSourceConsulKeys() *schema.Resource { } func dataSourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) vars := make(map[string]string) @@ -96,7 +87,7 @@ func dataSourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error { // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) d.SetId("-") diff --git a/consul/data_source_consul_keys_test.go b/consul/data_source_consul_keys_test.go index 90d061d8..fc4e331c 100644 --- a/consul/data_source_consul_keys_test.go +++ b/consul/data_source_consul_keys_test.go @@ -47,6 +47,22 @@ func TestAccDataConsulKeys_namespaceEE(t *testing.T) { }) } +func TestAccDataConsulKeys_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccDataConsulKeysConfigDatacenter, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsulKeysValue("data.consul_keys.dc1", "read", ""), + testAccCheckConsulKeysValue("data.consul_keys.dc2", "read", "dc2"), + ), + }, + }, + }) +} + const testAccDataConsulKeysConfig = ` resource "consul_keys" "write" { datacenter = "dc1" @@ -102,3 +118,31 @@ data "consul_keys" "read" { name = "read" } }` + +const testAccDataConsulKeysConfigDatacenter = ` +resource "consul_keys" "write" { + datacenter = "dc2" + + key { + path = "test/dc" + value = "dc2" + delete = true + } +} + +data "consul_keys" "dc1" { + key { + path = "test/dc" + name = "read" + } +} + +data "consul_keys" "dc2" { + datacenter = consul_keys.write.datacenter + + key { + path = "test/dc" + name = "read" + } +} +` diff --git a/consul/data_source_consul_network_area_members.go b/consul/data_source_consul_network_area_members.go index 9f74bbaf..cf16e3b2 100644 --- a/consul/data_source_consul_network_area_members.go +++ b/consul/data_source_consul_network_area_members.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -84,22 +83,12 @@ func dataSourceConsulNetworkAreaMembers() *schema.Resource { } func datasourceConsulNetworkAreaMembersRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() uuid := d.Get("uuid").(string) d.SetId(fmt.Sprintf("consul-network-area-members-%s", uuid)) - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - qOpts := &consulapi.QueryOptions{ - Token: token, - Datacenter: dc, - } members, _, err := operator.AreaMembers(uuid, qOpts) if err != nil { return fmt.Errorf("Failed to fetch the list of members: %v", err) diff --git a/consul/data_source_consul_network_area_members_test.go b/consul/data_source_consul_network_area_members_test.go index b97c32f6..c13290f4 100644 --- a/consul/data_source_consul_network_area_members_test.go +++ b/consul/data_source_consul_network_area_members_test.go @@ -42,6 +42,22 @@ func TestAccConsulNetworkAreaMembers_CommunityEdition(t *testing.T) { }) } +func TestAccConsulNetworkAreaMembers_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccRemoteDatacenterPreCheck(t) + skipTestOnConsulCommunityEdition(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccConsulNetworkAreaMembers_datacenter, + Check: resource.TestCheckResourceAttr("data.consul_network_area_members.test", "members.0.datacenter", "dc2"), + }, + }, + }) +} + const testAccConsulNetworkAreaMembersBasic = ` resource "consul_network_area" "test" { peer_datacenter = "foo" @@ -56,3 +72,15 @@ const testAccConsulNetworkAreaMembers_CommunityEdition = ` data "consul_network_area_members" "test" { uuid = "1.2.3.4" }` + +const testAccConsulNetworkAreaMembers_datacenter = ` +resource "consul_network_area" "test" { + datacenter = "dc2" + peer_datacenter = "foo" + retry_join = ["1.2.3.4"] +} + +data "consul_network_area_members" "test" { + datacenter = "dc2" + uuid = consul_network_area.test.id +}` diff --git a/consul/data_source_consul_network_segments.go b/consul/data_source_consul_network_segments.go index 34268010..ef4bf3ed 100644 --- a/consul/data_source_consul_network_segments.go +++ b/consul/data_source_consul_network_segments.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -36,25 +35,15 @@ func dataSourceConsulNetworkSegments() *schema.Resource { } func dataSourceConsulNetworkSegmentsRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - qOpts := &consulapi.QueryOptions{ - Token: token, - Datacenter: dc, - } segments, _, err := operator.SegmentList(qOpts) if err != nil { return fmt.Errorf("Failed to get segment list: %v", err) } - d.SetId(fmt.Sprintf("consul-segments-%s", dc)) + d.SetId(fmt.Sprintf("consul-segments-%s", qOpts.Datacenter)) if err := d.Set("segments", segments); err != nil { return fmt.Errorf("Failed to set 'segments': %v", err) } diff --git a/consul/data_source_consul_network_segments_test.go b/consul/data_source_consul_network_segments_test.go index 28f5e806..b120eefa 100644 --- a/consul/data_source_consul_network_segments_test.go +++ b/consul/data_source_consul_network_segments_test.go @@ -36,6 +36,28 @@ func TestAccConsulNetworkSegments_CommunityEdition(t *testing.T) { }) } +func TestAccConsulNetworkSegments_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccRemoteDatacenterPreCheck(t) + skipTestOnConsulCommunityEdition(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccConsulNetworkSegmentsDatacenter, + ExpectError: regexp.MustCompile("Failed to get segment list"), + }, + }, + }) +} + const testAccConsulNetworkSegmentsBasic = ` data "consul_network_segments" "test" {} ` + +const testAccConsulNetworkSegmentsDatacenter = ` +data "consul_network_segments" "test" { + datacenter = "dc3" +} +` diff --git a/consul/data_source_consul_nodes.go b/consul/data_source_consul_nodes.go index 5202f7e9..8112bc27 100644 --- a/consul/data_source_consul_nodes.go +++ b/consul/data_source_consul_nodes.go @@ -7,73 +7,53 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -const ( - catalogNodesElem = "nodes" - catalogNodesDatacenter = "datacenter" - catalogNodesQueryOpts = "query_options" - - catalogNodesNodeID = "id" - catalogNodesNodeAddress = "address" - catalogNodesNodeMeta = "meta" - catalogNodesNodeName = "name" - catalogNodesNodeTaggedAddresses = "tagged_addresses" - - catalogNodesNodeIDs = "node_ids" - catalogNodesNodeNames = "node_names" - - catalogNodesAPITaggedLAN = "lan" - catalogNodesAPITaggedWAN = "wan" - catalogNodesSchemaTaggedLAN = "lan" - catalogNodesSchemaTaggedWAN = "wan" -) - func dataSourceConsulNodes() *schema.Resource { return &schema.Resource{ Read: dataSourceConsulNodesRead, Schema: map[string]*schema.Schema{ // Filters - catalogNodesQueryOpts: schemaQueryOpts(), + "query_options": schemaQueryOpts(), // Out parameters - catalogNodesDatacenter: { + "datacenter": { Computed: true, Type: schema.TypeString, }, - catalogNodesNodeIDs: { + "node_ids": { Computed: true, Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, }, - catalogNodesNodeNames: { + "node_names": { Computed: true, Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, }, - catalogNodesElem: { + "nodes": { Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - catalogNodesNodeID: { + "id": { Type: schema.TypeString, Computed: true, }, - catalogNodesNodeName: { + "name": { Type: schema.TypeString, Computed: true, }, - catalogNodesNodeAddress: { + "address": { Type: schema.TypeString, Computed: true, }, - catalogNodesNodeMeta: { + "meta": { Type: schema.TypeMap, Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, }, - catalogNodesNodeTaggedAddresses: { + "tagged_addresses": { Type: schema.TypeMap, Computed: true, Elem: &schema.Schema{ @@ -88,15 +68,11 @@ func dataSourceConsulNodes() *schema.Resource { } func dataSourceConsulNodesRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - + client, qOpts, _ := getClient(d, meta) // Parse out data source filters to populate Consul's query options - queryOpts, err := getQueryOpts(d, client, meta) - if err != nil { - return errwrap.Wrapf("unable to get query options for fetching catalog nodes: {{err}}", err) - } + getQueryOpts(qOpts, d, meta) - nodes, meta, err := client.Catalog().Nodes(queryOpts) + nodes, meta, err := client.Catalog().Nodes(qOpts) if err != nil { return err } @@ -117,28 +93,28 @@ func dataSourceConsulNodesRead(d *schema.ResourceData, meta interface{}) error { nodeIDs = append(nodeIDs, id) nodeNames = append(nodeNames, node.Node) - m[catalogNodesNodeAddress] = node.Address - m[catalogNodesNodeID] = id - m[catalogNodesNodeName] = node.Node - m[catalogNodesNodeMeta] = node.Meta - m[catalogNodesNodeTaggedAddresses] = node.TaggedAddresses + m["address"] = node.Address + m["id"] = id + m["name"] = node.Node + m["meta"] = node.Meta + m["tagged_addresses"] = node.TaggedAddresses l = append(l, m) } const idKeyFmt = "catalog-nodes-%s" - d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) + d.SetId(fmt.Sprintf(idKeyFmt, qOpts.Datacenter)) - d.Set(catalogNodesDatacenter, queryOpts.Datacenter) - if err := d.Set(catalogNodesNodeIDs, nodeIDs); err != nil { + d.Set("datacenter", qOpts.Datacenter) + if err := d.Set("node_ids", nodeIDs); err != nil { return errwrap.Wrapf("Unable to store node IDs: {{err}}", err) } - if err := d.Set(catalogNodesNodeNames, nodeNames); err != nil { + if err := d.Set("node_names", nodeNames); err != nil { return errwrap.Wrapf("Unable to store node names: {{err}}", err) } - if err := d.Set(catalogNodesElem, l); err != nil { + if err := d.Set("nodes", l); err != nil { return errwrap.Wrapf("Unable to store nodes: {{err}}", err) } diff --git a/consul/data_source_consul_nodes_test.go b/consul/data_source_consul_nodes_test.go index 6cfb0c4a..e68efb67 100644 --- a/consul/data_source_consul_nodes_test.go +++ b/consul/data_source_consul_nodes_test.go @@ -23,6 +23,7 @@ func TestAccDataConsulNodes_basic(t *testing.T) { }, }) } + func TestAccDataConsulNodes_alias(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -38,6 +39,21 @@ func TestAccDataConsulNodes_alias(t *testing.T) { }) } +func TestAccDataConsulNodes_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataConsulNodesDatacenter, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.consul_catalog_nodes.read", "nodes.#", "2"), + ), + }, + }, + }) +} + const testAccDataConsulNodesConfig = ` data "consul_nodes" "read" { query_options { @@ -52,3 +68,17 @@ data "consul_nodes" "read" { const testAccDataConsulNodesAlias = ` data "consul_catalog_nodes" "read" {} ` + +const testAccDataConsulNodesDatacenter = ` +resource "consul_node" "dc2" { + datacenter = "dc2" + name = "dc2" + address = "127.0.0.1" +} + +data "consul_catalog_nodes" "read" { + query_options { + datacenter = consul_node.dc2.datacenter + } +} +` diff --git a/consul/data_source_consul_service.go b/consul/data_source_consul_service.go index ce19e37a..9845d139 100644 --- a/consul/data_source_consul_service.go +++ b/consul/data_source_consul_service.go @@ -64,7 +64,7 @@ func dataSourceConsulService() *schema.Resource { Optional: true, Type: schema.TypeString, }, - catalogNodesQueryOpts: queryOpts, + "query_options": queryOpts, // Out parameters catalogServiceElem: { @@ -146,13 +146,10 @@ func dataSourceConsulService() *schema.Resource { } func dataSourceConsulServiceRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) // Parse out data source filters to populate Consul's query options - queryOpts, err := getQueryOpts(d, client, meta) - if err != nil { - return errwrap.Wrapf("unable to get query options for fetching catalog services: {{err}}", err) - } + getQueryOpts(qOpts, d, meta) var serviceName string if v, ok := d.GetOk(catalogServiceName); ok { @@ -164,8 +161,7 @@ func dataSourceConsulServiceRead(d *schema.ResourceData, meta interface{}) error serviceTag = v.(string) } - // services, meta, err := client.Catalog().Services(queryOpts) - services, meta, err := client.Catalog().Service(serviceName, serviceTag, queryOpts) + services, meta, err := client.Catalog().Service(serviceName, serviceTag, qOpts) if err != nil { return err } @@ -200,9 +196,9 @@ func dataSourceConsulServiceRead(d *schema.ResourceData, meta interface{}) error } const idKeyFmt = "catalog-service-%s-%q-%q" - d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter, serviceName, serviceTag)) + d.SetId(fmt.Sprintf(idKeyFmt, qOpts.Datacenter, serviceName, serviceTag)) - d.Set(catalogServiceDatacenter, queryOpts.Datacenter) + d.Set(catalogServiceDatacenter, qOpts.Datacenter) d.Set(catalogServiceName, serviceName) d.Set(catalogServiceTag, serviceTag) if err := d.Set(catalogServiceElem, l); err != nil { diff --git a/consul/data_source_consul_service_health.go b/consul/data_source_consul_service_health.go index 6bb70619..3aac1946 100644 --- a/consul/data_source_consul_service_health.go +++ b/consul/data_source_consul_service_health.go @@ -190,7 +190,7 @@ func dataSourceConsulServiceHealth() *schema.Resource { } func dataSourceConsulServiceHealthRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOps, _ := getClient(d, meta) health := client.Health() serviceName := d.Get("name").(string) @@ -199,26 +199,15 @@ func dataSourceConsulServiceHealthRead(d *schema.ResourceData, meta interface{}) near := d.Get("near").(string) nodeMeta := d.Get("node_meta").(map[string]interface{}) - dc := d.Get("datacenter").(string) - if dc == "" { - var err error - dc, err = getDC(d, client, meta) - if err != nil { - return err - } - } - queryNodeMeta := map[string]string{} for key, value := range nodeMeta { queryNodeMeta[key] = value.(string) } - qOps := &consulapi.QueryOptions{ - Near: near, - NodeMeta: queryNodeMeta, - Datacenter: dc, - Filter: d.Get("filter").(string), - } + qOps.Near = near + qOps.NodeMeta = queryNodeMeta + qOps.Filter = d.Get("filter").(string) + var err error var serviceEntries []*consulapi.ServiceEntry if d.Get("wait_for").(string) == "" || !passingOnly { @@ -298,8 +287,8 @@ func dataSourceConsulServiceHealthRead(d *schema.ResourceData, meta interface{}) } const idKeyFmt = "service-health-%s-%q-%q" - d.SetId(fmt.Sprintf(idKeyFmt, dc, serviceName, serviceTag)) - if err = d.Set("datacenter", dc); err != nil { + d.SetId(fmt.Sprintf(idKeyFmt, qOps.Datacenter, serviceName, serviceTag)) + if err = d.Set("datacenter", qOps.Datacenter); err != nil { return fmt.Errorf("Failed to set 'datacenter': %s", err) } if err = d.Set("near", near); err != nil { diff --git a/consul/data_source_consul_service_health_test.go b/consul/data_source_consul_service_health_test.go index f08543c7..4adc63bd 100644 --- a/consul/data_source_consul_service_health_test.go +++ b/consul/data_source_consul_service_health_test.go @@ -92,6 +92,19 @@ func TestAccDataConsulServiceHealthPassing(t *testing.T) { }) } +func TestAccDataConsulServiceHealthDatacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataConsulServiceHealthDatacenter, + Check: testAccCheckDataSourceValue("data.consul_service_health.consul", "results.0.node.0.datacenter", "dc2"), + }, + }, + }) +} + const testAccDataConsulServiceHealth = ` data "consul_service_health" "consul" { name = "consul" @@ -198,3 +211,10 @@ data "consul_service_health" "google" { // wait_for = "10s" } ` + +const testAccDataConsulServiceHealthDatacenter = ` +data "consul_service_health" "consul" { + name = "consul" + datacenter = "dc2" +} +` diff --git a/consul/data_source_consul_services.go b/consul/data_source_consul_services.go index c8f8d800..f2b468fe 100644 --- a/consul/data_source_consul_services.go +++ b/consul/data_source_consul_services.go @@ -9,17 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -const ( - // Datasource predicates - catalogServicesServiceName = "name" - - // Out parameters - catalogServicesDatacenter = "datacenter" - catalogServicesNames = "names" - catalogServicesServices = "services" - catalogServicesServiceTags = "tags" -) - func dataSourceConsulServices() *schema.Resource { queryOpts := schemaQueryOpts() queryOpts.Elem.(*schema.Resource).Schema["namespace"] = &schema.Schema{ @@ -31,21 +20,21 @@ func dataSourceConsulServices() *schema.Resource { Read: dataSourceConsulServicesRead, Schema: map[string]*schema.Schema{ // Data Source Predicate(s) - catalogServicesDatacenter: { + "datacenter": { // Used in the query, must be stored and force a refresh if the value // changes. Computed: true, Type: schema.TypeString, }, - catalogNodesQueryOpts: queryOpts, + "query_options": queryOpts, // Out parameters - catalogServicesNames: { + "names": { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - catalogServicesServices: { + "services": { Computed: true, Type: schema.TypeMap, Elem: &schema.Schema{ @@ -57,15 +46,12 @@ func dataSourceConsulServices() *schema.Resource { } func dataSourceConsulServicesRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) // Parse out data source filters to populate Consul's query options - queryOpts, err := getQueryOpts(d, client, meta) - if err != nil { - return errwrap.Wrapf("unable to get query options for fetching catalog services: {{err}}", err) - } + getQueryOpts(qOpts, d, meta) - services, meta, err := client.Catalog().Services(queryOpts) + services, meta, err := client.Catalog().Services(qOpts) if err != nil { return err } @@ -73,10 +59,7 @@ func dataSourceConsulServicesRead(d *schema.ResourceData, meta interface{}) erro catalogServices := make(map[string]interface{}, len(services)) for name, tags := range services { tagList := make([]string, 0, len(tags)) - for _, tag := range tags { - tagList = append(tagList, tag) - } - + tagList = append(tagList, tags...) sort.Strings(tagList) catalogServices[name] = strings.Join(tagList, " ") } @@ -87,14 +70,14 @@ func dataSourceConsulServicesRead(d *schema.ResourceData, meta interface{}) erro } const idKeyFmt = "catalog-services-%s" - d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) + d.SetId(fmt.Sprintf(idKeyFmt, qOpts.Datacenter)) - d.Set(catalogServicesDatacenter, queryOpts.Datacenter) - if err := d.Set(catalogServicesServices, catalogServices); err != nil { + d.Set("datacenter", qOpts.Datacenter) + if err := d.Set("services", catalogServices); err != nil { return errwrap.Wrapf("Unable to store services: {{err}}", err) } - if err := d.Set(catalogServicesNames, serviceNames); err != nil { + if err := d.Set("names", serviceNames); err != nil { return errwrap.Wrapf("Unable to store service names: {{err}}", err) } diff --git a/consul/data_source_consul_services_test.go b/consul/data_source_consul_services_test.go index 8132fad7..c67eb082 100644 --- a/consul/data_source_consul_services_test.go +++ b/consul/data_source_consul_services_test.go @@ -31,9 +31,7 @@ func TestAccDataConsulCatalogServices_alias(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDataConsulCatalogServicesConfig, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.consul_services.read", "services.%", "1"), - ), + Check: resource.TestCheckResourceAttr("data.consul_services.read", "services.%", "1"), }, }, }) @@ -77,6 +75,19 @@ func TestAccDataConsulServices_namespaceEE(t *testing.T) { }) } +func TestAccDataConsulServices_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccDataConsulCatalogServicesDatacenter, + Check: testAccCheckDataSourceValue("data.consul_services.read", "services.%", "2"), + }, + }, + }) +} + const testAccDataConsulCatalogServicesConfig = ` data "consul_services" "read" { query_options { @@ -116,3 +127,24 @@ data "consul_services" "read" { } } ` + +const testAccDataConsulCatalogServicesDatacenter = ` +resource "consul_node" "test" { + datacenter = "dc2" + name = "test" + address = "test.com" +} + +resource "consul_service" "test" { + datacenter = "dc2" + name = "test" + node = consul_node.test.name + port = 80 +} + +data "consul_services" "read" { + query_options { + datacenter = consul_service.test.datacenter + } +} +` diff --git a/consul/key_client.go b/consul/key_client.go index 88f668af..f253190f 100644 --- a/consul/key_client.go +++ b/consul/key_client.go @@ -5,6 +5,7 @@ import ( "log" consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) // keyClient is a wrapper around the upstream Consul client that is @@ -15,20 +16,11 @@ type keyClient struct { wOpts *consulapi.WriteOptions } -func newKeyClient(realClient *consulapi.KV, dc, token, namespace string) *keyClient { - qOpts := &consulapi.QueryOptions{ - Datacenter: dc, - Token: token, - Namespace: namespace, - } - wOpts := &consulapi.WriteOptions{ - Datacenter: dc, - Token: token, - Namespace: namespace, - } +func newKeyClient(d *schema.ResourceData, meta interface{}) *keyClient { + client, qOpts, wOpts := getClient(d, meta) return &keyClient{ - client: realClient, + client: client.KV(), qOpts: qOpts, wOpts: wOpts, } diff --git a/consul/query_options.go b/consul/query_options.go index 8c21a18b..89161125 100644 --- a/consul/query_options.go +++ b/consul/query_options.go @@ -7,66 +7,55 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -const ( - queryOptAllowStale = "allow_stale" - queryOptDatacenter = "datacenter" - queryOptNear = "near" - queryOptNodeMeta = "node_meta" - queryOptRequireConsistent = "require_consistent" - queryOptToken = "token" - queryOptWaitIndex = "wait_index" - queryOptWaitTime = "wait_time" -) - func schemaQueryOpts() *schema.Schema { return &schema.Schema{ Optional: true, Type: schema.TypeSet, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - queryOptAllowStale: { + "allow_stale": { Optional: true, Default: true, Type: schema.TypeBool, }, - queryOptDatacenter: { + "datacenter": { // Optional because we'll pull the default from the local agent if it's // not specified, but we can query remote data centers as a result. Optional: true, Type: schema.TypeString, }, - queryOptNear: { + "near": { Optional: true, Type: schema.TypeString, }, - queryOptNodeMeta: { + "node_meta": { Optional: true, Type: schema.TypeMap, Elem: &schema.Schema{ Type: schema.TypeString, }, }, - queryOptRequireConsistent: { + "require_consistent": { Optional: true, Default: false, Type: schema.TypeBool, }, - queryOptToken: { + "token": { Optional: true, Type: schema.TypeString, Sensitive: true, }, - queryOptWaitIndex: { + "wait_index": { Optional: true, Type: schema.TypeInt, - ValidateFunc: makeValidationFunc(queryOptWaitIndex, []interface{}{ + ValidateFunc: makeValidationFunc("wait_index", []interface{}{ validateIntMin(0), }), }, - queryOptWaitTime: { + "wait_time": { Optional: true, Type: schema.TypeString, - ValidateFunc: makeValidationFunc(queryOptWaitTime, []interface{}{ + ValidateFunc: makeValidationFunc("wait_time", []interface{}{ validateDurationMin("0ns"), }), }, @@ -75,67 +64,57 @@ func schemaQueryOpts() *schema.Schema { } } -func getQueryOpts(d *schema.ResourceData, client *consulapi.Client, meta interface{}) (*consulapi.QueryOptions, error) { - queryOpts := &consulapi.QueryOptions{} - +func getQueryOpts(queryOpts *consulapi.QueryOptions, d *schema.ResourceData, meta interface{}) { if filter, ok := d.GetOk("filter"); ok { queryOpts.Filter = filter.(string) } - if v, ok := d.GetOk(catalogNodesQueryOpts); ok { + if v, ok := d.GetOk("query_options"); ok { for _, config := range v.(*schema.Set).List() { queryOptions := config.(map[string]interface{}) - if v, ok := queryOptions[queryOptAllowStale]; ok { + if v, ok := queryOptions["allow_stale"]; ok { queryOpts.AllowStale = v.(bool) } - if v, ok := queryOptions[queryOptDatacenter]; ok { - queryOpts.Datacenter = v.(string) + if v, ok := queryOptions["datacenter"]; ok { + if v.(string) != "" { + queryOpts.Datacenter = v.(string) + } } if v, ok := queryOptions["namespace"]; ok { queryOpts.Namespace = v.(string) } - if queryOpts.Datacenter == "" { - dc, err := getDC(d, client, meta) - if err != nil { - return nil, err - } - queryOpts.Datacenter = dc - } - - if v, ok := queryOptions[queryOptNear]; ok { + if v, ok := queryOptions["near"]; ok { queryOpts.Near = v.(string) } - if v, ok := queryOptions[queryOptRequireConsistent]; ok { + if v, ok := queryOptions["require_consistent"]; ok { queryOpts.RequireConsistent = v.(bool) } - if v, ok := queryOptions[queryOptNodeMeta]; ok { + if v, ok := queryOptions["node_meta"]; ok { m := v.(map[string]interface{}) - nodeMetaMap := make(map[string]string, len(queryOptNodeMeta)) + nodeMetaMap := make(map[string]string, len("node_meta")) for s, t := range m { nodeMetaMap[s] = t.(string) } queryOpts.NodeMeta = nodeMetaMap } - if v, ok := queryOptions[queryOptToken]; ok { + if v, ok := queryOptions["token"]; ok { queryOpts.Token = v.(string) } - if v, ok := queryOptions[queryOptWaitIndex]; ok { + if v, ok := queryOptions["wait_index"]; ok { queryOpts.WaitIndex = uint64(v.(int)) } - if v, ok := queryOptions[queryOptWaitTime]; ok { + if v, ok := queryOptions["wait_time"]; ok { d, _ := time.ParseDuration(v.(string)) queryOpts.WaitTime = d } } } - - return queryOpts, nil } diff --git a/consul/resource_consul_acl_auth_method.go b/consul/resource_consul_acl_auth_method.go index 434414ed..7abc890d 100644 --- a/consul/resource_consul_acl_auth_method.go +++ b/consul/resource_consul_acl_auth_method.go @@ -127,8 +127,8 @@ func resourceConsulACLAuthMethod() *schema.Resource { } func resourceConsulACLAuthMethodCreate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() authMethod, err := getAuthMethod(d, meta) if err != nil { @@ -143,11 +143,8 @@ func resourceConsulACLAuthMethodCreate(d *schema.ResourceData, meta interface{}) } func resourceConsulACLAuthMethodRead(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - namespace := getNamespace(d, meta) - qOpts := &consulapi.QueryOptions{ - Namespace: namespace, - } + client, qOpts, _ := getClient(d, meta) + ACL := client.ACL() name := d.Get("name").(string) authMethod, _, err := ACL.AuthMethodRead(name, qOpts) @@ -219,8 +216,8 @@ func resourceConsulACLAuthMethodRead(d *schema.ResourceData, meta interface{}) e } func resourceConsulACLAuthMethodUpdate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() authMethod, err := getAuthMethod(d, meta) if err != nil { @@ -235,11 +232,8 @@ func resourceConsulACLAuthMethodUpdate(d *schema.ResourceData, meta interface{}) } func resourceConsulACLAuthMethodDelete(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - namespace := getNamespace(d, meta) - wOpts := &consulapi.WriteOptions{ - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() authMethodName := d.Get("name").(string) if _, err := ACL.AuthMethodDelete(authMethodName, wOpts); err != nil { @@ -251,7 +245,7 @@ func resourceConsulACLAuthMethodDelete(d *schema.ResourceData, meta interface{}) } func getAuthMethod(d *schema.ResourceData, meta interface{}) (*consulapi.ACLAuthMethod, error) { - namespace := getNamespace(d, meta) + _, qOpts, _ := getClient(d, meta) var config map[string]interface{} if c := d.Get("config_json").(string); c != "" { @@ -270,7 +264,7 @@ func getAuthMethod(d *schema.ResourceData, meta interface{}) (*consulapi.ACLAuth Type: d.Get("type").(string), Description: d.Get("description").(string), Config: config, - Namespace: namespace, + Namespace: qOpts.Namespace, } if mtt, ok := d.GetOk("max_token_ttl"); ok { diff --git a/consul/resource_consul_acl_auth_method_test.go b/consul/resource_consul_acl_auth_method_test.go index 59884cb4..44b9b8c4 100644 --- a/consul/resource_consul_acl_auth_method_test.go +++ b/consul/resource_consul_acl_auth_method_test.go @@ -118,7 +118,7 @@ func TestAccConsulACLAuthMethod_namespaceEE(t *testing.T) { func testAuthMethodCACert(name, v string) func(s *terraform.State) error { return func(s *terraform.State) error { - ACL := getClient(testAccProvider.Meta()).ACL() + ACL := getTestClient(testAccProvider.Meta()).ACL() authMethod, _, err := ACL.AuthMethodRead(name, nil) if err != nil { @@ -140,7 +140,7 @@ func testAuthMethodCACert(name, v string) func(s *terraform.State) error { } func testAuthMethodDestroy(s *terraform.State) error { - ACL := getClient(testAccProvider.Meta()).ACL() + ACL := getTestClient(testAccProvider.Meta()).ACL() qOpts := &consulapi.QueryOptions{} role, _, err := ACL.AuthMethodRead("minikube2", qOpts) diff --git a/consul/resource_consul_acl_binding_rule.go b/consul/resource_consul_acl_binding_rule.go index 8744f31f..fcaf96f6 100644 --- a/consul/resource_consul_acl_binding_rule.go +++ b/consul/resource_consul_acl_binding_rule.go @@ -56,8 +56,8 @@ func resourceConsulACLBindingRule() *schema.Resource { } func resourceConsulACLBindingRuleCreate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() rule := getBindingRule(d, meta) @@ -72,11 +72,8 @@ func resourceConsulACLBindingRuleCreate(d *schema.ResourceData, meta interface{} } func resourceConsulACLBindingRuleRead(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - namespace := getNamespace(d, meta) - qOpts := &consulapi.QueryOptions{ - Namespace: namespace, - } + client, qOpts, _ := getClient(d, meta) + ACL := client.ACL() rule, _, err := ACL.BindingRuleRead(d.Id(), qOpts) if err != nil { @@ -107,8 +104,8 @@ func resourceConsulACLBindingRuleRead(d *schema.ResourceData, meta interface{}) } func resourceConsulACLBindingRuleUpdate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() rule := getBindingRule(d, meta) @@ -121,11 +118,8 @@ func resourceConsulACLBindingRuleUpdate(d *schema.ResourceData, meta interface{} } func resourceConsulACLBindingRuleDelete(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - namespace := getNamespace(d, meta) - wOpts := &consulapi.WriteOptions{ - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() if _, err := ACL.BindingRuleDelete(d.Id(), wOpts); err != nil { return fmt.Errorf("Failed to delete binding rule '%s': %v", d.Id(), err) @@ -137,6 +131,7 @@ func resourceConsulACLBindingRuleDelete(d *schema.ResourceData, meta interface{} } func getBindingRule(d *schema.ResourceData, meta interface{}) *consulapi.ACLBindingRule { + _, _, wOpts := getClient(d, meta) return &consulapi.ACLBindingRule{ ID: d.Id(), Description: d.Get("description").(string), @@ -144,6 +139,6 @@ func getBindingRule(d *schema.ResourceData, meta interface{}) *consulapi.ACLBind Selector: d.Get("selector").(string), BindName: d.Get("bind_name").(string), BindType: consulapi.BindingRuleBindType(d.Get("bind_type").(string)), - Namespace: getNamespace(d, meta), + Namespace: wOpts.Namespace, } } diff --git a/consul/resource_consul_acl_binding_rule_test.go b/consul/resource_consul_acl_binding_rule_test.go index 0f1179bf..7fb2208b 100644 --- a/consul/resource_consul_acl_binding_rule_test.go +++ b/consul/resource_consul_acl_binding_rule_test.go @@ -81,7 +81,7 @@ func TestAccConsulACLBindingRule_namespaceEE(t *testing.T) { } func testBindingRuleDestroy(s *terraform.State) error { - ACL := getClient(testAccProvider.Meta()).ACL() + ACL := getTestClient(testAccProvider.Meta()).ACL() qOpts := &consulapi.QueryOptions{} rules, _, err := ACL.BindingRuleList("minikube2", qOpts) diff --git a/consul/resource_consul_acl_policy.go b/consul/resource_consul_acl_policy.go index a28dc8a1..2cb7cb8c 100644 --- a/consul/resource_consul_acl_policy.go +++ b/consul/resource_consul_acl_policy.go @@ -52,7 +52,7 @@ func resourceConsulACLPolicy() *schema.Resource { } func resourceConsulACLPolicyCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) log.Printf("[DEBUG] Creating ACL policy") @@ -60,7 +60,7 @@ func resourceConsulACLPolicyCreate(d *schema.ResourceData, meta interface{}) err Name: d.Get("name").(string), Description: d.Get("description").(string), Rules: d.Get("rules").(string), - Namespace: getNamespace(d, meta), + Namespace: wOpts.Namespace, } if v, ok := d.GetOk("datacenters"); ok { @@ -72,7 +72,7 @@ func resourceConsulACLPolicyCreate(d *schema.ResourceData, meta interface{}) err aclPolicy.Datacenters = s } - policy, _, err := client.ACL().PolicyCreate(&aclPolicy, nil) + policy, _, err := client.ACL().PolicyCreate(&aclPolicy, wOpts) if err != nil { return fmt.Errorf("error creating ACL policy: %s", err) } @@ -85,10 +85,7 @@ func resourceConsulACLPolicyCreate(d *schema.ResourceData, meta interface{}) err } func resourceConsulACLPolicyRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - qOpts := &consulapi.QueryOptions{ - Namespace: getNamespace(d, meta), - } + client, qOpts, _ := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL policy %q", id) @@ -128,7 +125,7 @@ func resourceConsulACLPolicyRead(d *schema.ResourceData, meta interface{}) error } func resourceConsulACLPolicyUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Updating ACL policy %q", id) @@ -138,7 +135,7 @@ func resourceConsulACLPolicyUpdate(d *schema.ResourceData, meta interface{}) err Name: d.Get("name").(string), Description: d.Get("description").(string), Rules: d.Get("rules").(string), - Namespace: getNamespace(d, meta), + Namespace: wOpts.Namespace, } if v, ok := d.GetOk("datacenters"); ok { @@ -150,7 +147,7 @@ func resourceConsulACLPolicyUpdate(d *schema.ResourceData, meta interface{}) err aclPolicy.Datacenters = s } - _, _, err := client.ACL().PolicyUpdate(&aclPolicy, nil) + _, _, err := client.ACL().PolicyUpdate(&aclPolicy, wOpts) if err != nil { return fmt.Errorf("error updating ACL policy %q: %s", id, err) } @@ -160,10 +157,7 @@ func resourceConsulACLPolicyUpdate(d *schema.ResourceData, meta interface{}) err } func resourceConsulACLPolicyDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - wOpts := &consulapi.WriteOptions{ - Namespace: getNamespace(d, meta), - } + client, _, wOpts := getClient(d, meta) id := d.Id() diff --git a/consul/resource_consul_acl_policy_test.go b/consul/resource_consul_acl_policy_test.go index 5f8e72e7..00ef7062 100644 --- a/consul/resource_consul_acl_policy_test.go +++ b/consul/resource_consul_acl_policy_test.go @@ -9,7 +9,7 @@ import ( ) func testAccCheckConsulACLPolicyDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) for _, rs := range s.RootModule().Resources { if rs.Type != "consul_acl_policy" { diff --git a/consul/resource_consul_acl_role.go b/consul/resource_consul_acl_role.go index a6a4ba09..3cc9eb5f 100644 --- a/consul/resource_consul_acl_role.go +++ b/consul/resource_consul_acl_role.go @@ -71,9 +71,9 @@ func resourceConsulACLRole() *schema.Resource { } func resourceConsulACLRoleCreate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() role := getRole(d, meta) - wOpts := &consulapi.WriteOptions{} name := role.Name role, _, err := ACL.RoleCreate(role, wOpts) @@ -86,10 +86,8 @@ func resourceConsulACLRoleCreate(d *schema.ResourceData, meta interface{}) error } func resourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - qOpts := &consulapi.QueryOptions{ - Namespace: getNamespace(d, meta), - } + client, qOpts, _ := getClient(d, meta) + ACL := client.ACL() role, _, err := ACL.RoleRead(d.Id(), qOpts) if err != nil { @@ -138,9 +136,9 @@ func resourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error { } func resourceConsulACLRoleUpdate(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() role := getRole(d, meta) - wOpts := &consulapi.WriteOptions{} role.ID = d.Id() @@ -154,8 +152,8 @@ func resourceConsulACLRoleUpdate(d *schema.ResourceData, meta interface{}) error } func resourceConsulACLRoleDelete(d *schema.ResourceData, meta interface{}) error { - ACL := getClient(meta).ACL() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) + ACL := client.ACL() if _, err := ACL.RoleDelete(d.Id(), wOpts); err != nil { return fmt.Errorf("Failed to delete role '%s': %s", d.Id(), err) @@ -166,12 +164,12 @@ func resourceConsulACLRoleDelete(d *schema.ResourceData, meta interface{}) error } func getRole(d *schema.ResourceData, meta interface{}) *consulapi.ACLRole { - namespace := getNamespace(d, meta) + _, qOpts, _ := getClient(d, meta) roleName := d.Get("name").(string) role := &consulapi.ACLRole{ Name: roleName, Description: d.Get("description").(string), - Namespace: namespace, + Namespace: qOpts.Namespace, } policies := make([]*consulapi.ACLRolePolicyLink, 0) for _, raw := range d.Get("policies").(*schema.Set).List() { diff --git a/consul/resource_consul_acl_role_test.go b/consul/resource_consul_acl_role_test.go index 64795a82..0d3c6c12 100644 --- a/consul/resource_consul_acl_role_test.go +++ b/consul/resource_consul_acl_role_test.go @@ -101,7 +101,7 @@ func TestAccConsulACLRole_NamespaceEE(t *testing.T) { } func testRoleDestroy(s *terraform.State) error { - ACL := getClient(testAccProvider.Meta()).ACL() + ACL := getTestClient(testAccProvider.Meta()).ACL() qOpts := &consulapi.QueryOptions{} role, _, err := ACL.RoleReadByName("baz", qOpts) diff --git a/consul/resource_consul_acl_token.go b/consul/resource_consul_acl_token.go index 65c1fddc..56fac9ed 100644 --- a/consul/resource_consul_acl_token.go +++ b/consul/resource_consul_acl_token.go @@ -66,11 +66,7 @@ func resourceConsulACLToken() *schema.Resource { } func resourceConsulACLTokenCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - wOpts := &consulapi.WriteOptions{ - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) log.Printf("[DEBUG] Creating ACL token") @@ -89,11 +85,7 @@ func resourceConsulACLTokenCreate(d *schema.ResourceData, meta interface{}) erro } func resourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - qOpts := &consulapi.QueryOptions{ - Namespace: namespace, - } + client, qOpts, _ := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL token %q", id) @@ -144,11 +136,7 @@ func resourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error } func resourceConsulACLTokenUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - wOpts := &consulapi.WriteOptions{ - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Updating ACL token %q", id) @@ -166,11 +154,7 @@ func resourceConsulACLTokenUpdate(d *schema.ResourceData, meta interface{}) erro } func resourceConsulACLTokenDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - wOpts := &consulapi.WriteOptions{ - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) id := d.Id() diff --git a/consul/resource_consul_acl_token_policy_attachment.go b/consul/resource_consul_acl_token_policy_attachment.go index 5ed2d50e..88582c06 100644 --- a/consul/resource_consul_acl_token_policy_attachment.go +++ b/consul/resource_consul_acl_token_policy_attachment.go @@ -36,13 +36,13 @@ func resourceConsulACLTokenPolicyAttachment() *schema.Resource { } func resourceConsulACLTokenPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) log.Printf("[DEBUG] Creating ACL token policy attachment") tokenID := d.Get("token_id").(string) - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { return fmt.Errorf("Token '%s' not found", tokenID) } @@ -73,7 +73,7 @@ func resourceConsulACLTokenPolicyAttachmentCreate(d *schema.ResourceData, meta i } func resourceConsulACLTokenPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL token policy attachment '%q'", id) @@ -83,7 +83,7 @@ func resourceConsulACLTokenPolicyAttachmentRead(d *schema.ResourceData, meta int return fmt.Errorf("Invalid ACL token policy attachment id '%q'", id) } - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { if strings.Contains(err.Error(), "ACL not found") { log.Printf("[WARN] ACL token not found, removing from state") @@ -119,7 +119,7 @@ func resourceConsulACLTokenPolicyAttachmentRead(d *schema.ResourceData, meta int } func resourceConsulACLTokenPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, wOpts := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL token policy attachment '%q'", id) @@ -129,7 +129,7 @@ func resourceConsulACLTokenPolicyAttachmentDelete(d *schema.ResourceData, meta i return fmt.Errorf("Invalid ACL token policy attachment id '%q'", id) } - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { return fmt.Errorf("Token '%s' not found", tokenID) } @@ -141,7 +141,7 @@ func resourceConsulACLTokenPolicyAttachmentDelete(d *schema.ResourceData, meta i } } - _, _, err = client.ACL().TokenUpdate(aclToken, nil) + _, _, err = client.ACL().TokenUpdate(aclToken, wOpts) if err != nil { return fmt.Errorf("Error updating ACL token '%q' to set new policy attachment: '%s'", tokenID, err) } diff --git a/consul/resource_consul_acl_token_policy_attachment_test.go b/consul/resource_consul_acl_token_policy_attachment_test.go index fdac1054..8ec3e3d0 100644 --- a/consul/resource_consul_acl_token_policy_attachment_test.go +++ b/consul/resource_consul_acl_token_policy_attachment_test.go @@ -9,7 +9,7 @@ import ( ) func testAccCheckConsulACLTokenPolicyAttachmentDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) for _, rs := range s.RootModule().Resources { if rs.Type != "consul_acl_token_policy_attachment" { @@ -42,7 +42,7 @@ func testAccCheckTokenPolicyID(s *terraform.State) error { return fmt.Errorf("No token ID is set") } - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) _, _, err := client.ACL().TokenRead(tokenID, nil) if err != nil { return fmt.Errorf("Unable to retrieve token %q", tokenID) diff --git a/consul/resource_consul_acl_token_role_attachment.go b/consul/resource_consul_acl_token_role_attachment.go index de3e72d2..3c864b1f 100644 --- a/consul/resource_consul_acl_token_role_attachment.go +++ b/consul/resource_consul_acl_token_role_attachment.go @@ -36,13 +36,13 @@ func resourceConsulACLTokenRoleAttachment() *schema.Resource { } func resourceConsulACLTokenRoleAttachmentCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, wOpts := getClient(d, meta) log.Printf("[DEBUG] Creating ACL token role attachment") tokenID := d.Get("token_id").(string) - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { return fmt.Errorf("Token '%s' not found", tokenID) } @@ -58,7 +58,7 @@ func resourceConsulACLTokenRoleAttachmentCreate(d *schema.ResourceData, meta int Name: roleName, }) - _, _, err = client.ACL().TokenUpdate(aclToken, nil) + _, _, err = client.ACL().TokenUpdate(aclToken, wOpts) if err != nil { return fmt.Errorf("Error updating ACL token '%q' to set new role attachment: '%s'", tokenID, err) } @@ -73,7 +73,7 @@ func resourceConsulACLTokenRoleAttachmentCreate(d *schema.ResourceData, meta int } func resourceConsulACLTokenRoleAttachmentRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL token role attachment '%q'", id) @@ -83,7 +83,7 @@ func resourceConsulACLTokenRoleAttachmentRead(d *schema.ResourceData, meta inter return fmt.Errorf("Invalid ACL token role attachment id '%q'", id) } - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { if strings.Contains(err.Error(), "ACL not found") { log.Printf("[WARN] ACL token not found, removing from state") @@ -119,7 +119,7 @@ func resourceConsulACLTokenRoleAttachmentRead(d *schema.ResourceData, meta inter } func resourceConsulACLTokenRoleAttachmentDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, wOpts := getClient(d, meta) id := d.Id() log.Printf("[DEBUG] Reading ACL token role attachment '%q'", id) @@ -129,7 +129,7 @@ func resourceConsulACLTokenRoleAttachmentDelete(d *schema.ResourceData, meta int return fmt.Errorf("Invalid ACL token role attachment id '%q'", id) } - aclToken, _, err := client.ACL().TokenRead(tokenID, nil) + aclToken, _, err := client.ACL().TokenRead(tokenID, qOpts) if err != nil { return fmt.Errorf("Token '%s' not found", tokenID) } @@ -141,7 +141,7 @@ func resourceConsulACLTokenRoleAttachmentDelete(d *schema.ResourceData, meta int } } - _, _, err = client.ACL().TokenUpdate(aclToken, nil) + _, _, err = client.ACL().TokenUpdate(aclToken, wOpts) if err != nil { return fmt.Errorf("Error updating ACL token '%q' to set new role attachment: '%s'", tokenID, err) } diff --git a/consul/resource_consul_acl_token_role_attachment_test.go b/consul/resource_consul_acl_token_role_attachment_test.go index 952c4b59..79526d4c 100644 --- a/consul/resource_consul_acl_token_role_attachment_test.go +++ b/consul/resource_consul_acl_token_role_attachment_test.go @@ -9,7 +9,7 @@ import ( ) func testAccCheckConsulACLTokenRoleAttachmentDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) for _, rs := range s.RootModule().Resources { if rs.Type != "consul_acl_token_role_attachment" { @@ -42,7 +42,7 @@ func testAccCheckTokenRoleName(s *terraform.State) error { return fmt.Errorf("No token ID is set") } - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) _, _, err := client.ACL().TokenRead(tokenID, nil) if err != nil { return fmt.Errorf("Unable to retrieve token %q", tokenID) diff --git a/consul/resource_consul_acl_token_test.go b/consul/resource_consul_acl_token_test.go index 327b0496..1df8974d 100644 --- a/consul/resource_consul_acl_token_test.go +++ b/consul/resource_consul_acl_token_test.go @@ -9,7 +9,7 @@ import ( ) func testAccCheckConsulACLTokenDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) for _, rs := range s.RootModule().Resources { if rs.Type != "consul_acl_token" { diff --git a/consul/resource_consul_agent_service.go b/consul/resource_consul_agent_service.go index e06f4725..3073202a 100644 --- a/consul/resource_consul_agent_service.go +++ b/consul/resource_consul_agent_service.go @@ -45,7 +45,7 @@ func resourceConsulAgentService() *schema.Resource { } func resourceConsulAgentServiceCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, _ := getClient(d, meta) agent := client.Agent() name := d.Get("name").(string) @@ -94,7 +94,7 @@ func resourceConsulAgentServiceCreate(d *schema.ResourceData, meta interface{}) } func resourceConsulAgentServiceRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, _ := getClient(d, meta) agent := client.Agent() name := d.Get("name").(string) @@ -120,7 +120,7 @@ func resourceConsulAgentServiceRead(d *schema.ResourceData, meta interface{}) er } func resourceConsulAgentServiceDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, _ := getClient(d, meta) catalog := client.Agent() id := d.Id() diff --git a/consul/resource_consul_agent_service_test.go b/consul/resource_consul_agent_service_test.go index 9e88d50f..e9d533ba 100644 --- a/consul/resource_consul_agent_service_test.go +++ b/consul/resource_consul_agent_service_test.go @@ -32,7 +32,7 @@ func TestAccConsulAgentService_basic(t *testing.T) { } func testAccCheckConsulAgentServiceDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) agent := client.Agent() services, err := agent.Services() if err != nil { @@ -47,7 +47,7 @@ func testAccCheckConsulAgentServiceDestroy(s *terraform.State) error { func testAccCheckConsulAgentServiceExists() resource.TestCheckFunc { return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) agent := client.Agent() services, err := agent.Services() if err != nil { diff --git a/consul/resource_consul_autopilot_config.go b/consul/resource_consul_autopilot_config.go index 891866e6..e48da718 100644 --- a/consul/resource_consul_autopilot_config.go +++ b/consul/resource_consul_autopilot_config.go @@ -18,31 +18,31 @@ func resourceConsulAutopilotConfig() *schema.Resource { Delete: resourceConsulAutopilotConfigDelete, Schema: map[string]*schema.Schema{ - "datacenter": &schema.Schema{ + "datacenter": { Type: schema.TypeString, Optional: true, }, - "cleanup_dead_servers": &schema.Schema{ + "cleanup_dead_servers": { Type: schema.TypeBool, Optional: true, Default: true, }, - "last_contact_threshold": &schema.Schema{ + "last_contact_threshold": { Type: schema.TypeString, Optional: true, Default: "200ms", }, - "max_trailing_logs": &schema.Schema{ + "max_trailing_logs": { Type: schema.TypeInt, Optional: true, Default: 250, }, - "server_stabilization_time": &schema.Schema{ + "server_stabilization_time": { Type: schema.TypeString, Optional: true, Default: "10s", }, - "redundancy_zone_tag": &schema.Schema{ + "redundancy_zone_tag": { Type: schema.TypeString, Optional: true, Default: "", @@ -66,14 +66,9 @@ func resourceConsulAutopilotConfigCreate(d *schema.ResourceData, meta interface{ } func resourceConsulAutopilotConfigUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - lastContactThreshold, err := time.ParseDuration(d.Get("last_contact_threshold").(string)) if err != nil { return fmt.Errorf("Could not parse '%v': %v", "last_contact_threshold", err) @@ -92,9 +87,6 @@ func resourceConsulAutopilotConfigUpdate(d *schema.ResourceData, meta interface{ DisableUpgradeMigration: d.Get("disable_upgrade_migration").(bool), UpgradeVersionTag: d.Get("upgrade_version_tag").(string), } - wOpts := &consulapi.WriteOptions{ - Datacenter: dc, - } err = operator.AutopilotSetConfiguration(config, wOpts) if err != nil { return fmt.Errorf("Failed to update autopilot configuration: %v", err) @@ -104,23 +96,15 @@ func resourceConsulAutopilotConfigUpdate(d *schema.ResourceData, meta interface{ } func resourceConsulAutopilotConfigRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - qOpts := &consulapi.QueryOptions{ - Datacenter: dc, - } config, err := operator.AutopilotGetConfiguration(qOpts) if err != nil { return fmt.Errorf("Failed to fetch autopilot configuration: %v", err) } - d.SetId(fmt.Sprintf("consul-autopilot-%s", dc)) + d.SetId(fmt.Sprintf("consul-autopilot-%s", qOpts.Datacenter)) if err = d.Set("cleanup_dead_servers", config.CleanupDeadServers); err != nil { return errwrap.Wrapf("Unable to store cleanup_dead_servers: {{err}}", err) diff --git a/consul/resource_consul_autopilot_config_test.go b/consul/resource_consul_autopilot_config_test.go index 5620ad63..051ed0ed 100644 --- a/consul/resource_consul_autopilot_config_test.go +++ b/consul/resource_consul_autopilot_config_test.go @@ -16,7 +16,7 @@ func TestAccConsulAutopilotConfig_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testFinalConfiguration, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccConsulAutopilotConfigBasic, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("consul_autopilot_config.config", "id", "consul-autopilot-dc1"), @@ -29,7 +29,7 @@ func TestAccConsulAutopilotConfig_basic(t *testing.T) { resource.TestCheckResourceAttr("consul_autopilot_config.config", "upgrade_version_tag", ""), ), }, - resource.TestStep{ + { Config: testAccConsulAutopilotConfig, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("consul_autopilot_config.config", "id", "consul-autopilot-dc1"), @@ -52,7 +52,7 @@ func TestAccConsulAutopilotConfig_parseduration(t *testing.T) { PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccConsulAutopilotConfigParseDuration, ExpectError: errorRegexp, }, @@ -60,10 +60,44 @@ func TestAccConsulAutopilotConfig_parseduration(t *testing.T) { }) } +func TestAccConsulAutopilogConfig_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccConsulAutopilotDatacenter, + Check: func(s *terraform.State) error { + test := func(dc string, expected int) error { + c := getTestClient(testAccProvider.Meta()).Operator() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + autopilot, err := c.AutopilotGetConfiguration(opts) + if err != nil { + return err + } + + if autopilot.MaxTrailingLogs != uint64(expected) { + return fmt.Errorf("wrong value: %d", autopilot.MaxTrailingLogs) + } + return nil + } + + if err := test("dc1", 100); err != nil { + return err + } + return test("dc2", 10) + }, + }, + }, + }) +} + // when destroying the consul_autopilot_config resource, the configuration // should not be changed func testFinalConfiguration(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) operator := client.Operator() qOpts := &consulapi.QueryOptions{} config, err := operator.AutopilotGetConfiguration(qOpts) @@ -114,3 +148,10 @@ resource "consul_autopilot_config" "config" { last_contact_threshold = "one minute" } ` + +const testAccConsulAutopilotDatacenter = ` +resource "consul_autopilot_config" "config" { + datacenter = "dc2" + max_trailing_logs = 10 +} +` diff --git a/consul/resource_consul_catalog_entry.go b/consul/resource_consul_catalog_entry.go index 648e23b6..891b99af 100644 --- a/consul/resource_consul_catalog_entry.go +++ b/consul/resource_consul_catalog_entry.go @@ -118,27 +118,9 @@ func resourceConsulCatalogEntryServicesHash(v interface{}) int { } func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, wOpts := getClient(d, meta) catalog := client.Catalog() - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } else { - var err error - if dc, err = getDC(d, client, meta); err != nil { - return err - } - } - - var token string - if v, ok := d.GetOk("token"); ok { - token = v.(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token} - address := d.Get("address").(string) node := d.Get("node").(string) @@ -165,7 +147,7 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{}) registration := &consulapi.CatalogRegistration{ Address: address, - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: node, Service: &consulapi.AgentService{ Address: serviceData["address"].(string), @@ -176,31 +158,30 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{}) }, } - if _, err := catalog.Register(registration, &wOpts); err != nil { + if _, err := catalog.Register(registration, wOpts); err != nil { return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' in %s: %v", - node, address, dc, err) + node, address, wOpts.Datacenter, err) } } } else { registration := &consulapi.CatalogRegistration{ Address: address, - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: node, } - if _, err := catalog.Register(registration, &wOpts); err != nil { + if _, err := catalog.Register(registration, wOpts); err != nil { return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' in %s: %v", - node, address, dc, err) + node, address, wOpts.Datacenter, err) } } // Update the resource - qOpts := consulapi.QueryOptions{Datacenter: dc} - if _, _, err := catalog.Node(node, &qOpts); err != nil { + if _, _, err := catalog.Node(node, qOpts); err != nil { return fmt.Errorf("Failed to read Consul catalog entry for node '%s' at address '%s' in %s: %v", - node, address, dc, err) + node, address, qOpts.Datacenter, err) } else { - d.Set("datacenter", dc) + d.Set("datacenter", qOpts.Datacenter) } sort.Strings(serviceIDs) @@ -212,21 +193,12 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{}) } func resourceConsulCatalogEntryRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) catalog := client.Catalog() - // Get the DC, error if not available. - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } - node := d.Get("node").(string) - // Setup the operations using the datacenter - qOpts := consulapi.QueryOptions{Datacenter: dc} - - cNode, _, err := catalog.Node(node, &qOpts) + cNode, _, err := catalog.Node(node, qOpts) if err != nil { return fmt.Errorf("Failed to get node '%s' from Consul catalog: %v", node, err) } @@ -238,39 +210,21 @@ func resourceConsulCatalogEntryRead(d *schema.ResourceData, meta interface{}) er } func resourceConsulCatalogEntryDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) catalog := client.Catalog() - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } else { - var err error - if dc, err = getDC(d, client, meta); err != nil { - return err - } - } - - var token string - if v, ok := d.GetOk("token"); ok { - token = v.(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token} - address := d.Get("address").(string) node := d.Get("node").(string) deregistration := consulapi.CatalogDeregistration{ Address: address, - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: node, } - if _, err := catalog.Deregister(&deregistration, &wOpts); err != nil { + if _, err := catalog.Deregister(&deregistration, wOpts); err != nil { return fmt.Errorf("Failed to deregister Consul catalog entry with node '%s' at address '%s' in %s: %v", - node, address, dc, err) + node, address, wOpts.Datacenter, err) } // Clear the ID diff --git a/consul/resource_consul_catalog_entry_test.go b/consul/resource_consul_catalog_entry_test.go index 00c3f873..fa61d5db 100644 --- a/consul/resource_consul_catalog_entry_test.go +++ b/consul/resource_consul_catalog_entry_test.go @@ -64,7 +64,7 @@ func TestAccConsulCatalogEntry_extremove(t *testing.T) { } func testAccCheckConsulCatalogEntryDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() qOpts := consulapi.QueryOptions{} services, _, err := catalog.Services(&qOpts) @@ -80,7 +80,7 @@ func testAccCheckConsulCatalogEntryDestroy(s *terraform.State) error { func testAccCheckConsulCatalogEntryDeregister(node string) resource.TestCheckFunc { return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() wOpts := consulapi.WriteOptions{} @@ -107,7 +107,7 @@ func testAccCheckConsulCatalogEntryDeregister(node string) resource.TestCheckFun func testAccCheckConsulCatalogEntryExists() resource.TestCheckFunc { return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() qOpts := consulapi.QueryOptions{} services, _, err := catalog.Services(&qOpts) diff --git a/consul/resource_consul_certificate_authority.go b/consul/resource_consul_certificate_authority.go index 3587e2a2..520db2ca 100644 --- a/consul/resource_consul_certificate_authority.go +++ b/consul/resource_consul_certificate_authority.go @@ -34,14 +34,14 @@ func resourceConsulCertificateAuthority() *schema.Resource { } func resourceConsulCertificateAuthorityCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Connect() + client, _, wOpts := getClient(d, meta) caConfig := &consulapi.CAConfig{ Provider: d.Get("connect_provider").(string), Config: d.Get("config").(map[string]interface{}), } - if _, err := client.CASetConfig(caConfig, nil); err != nil { + if _, err := client.Connect().CASetConfig(caConfig, wOpts); err != nil { return fmt.Errorf("Failed to set CA configuration: %v", err) } @@ -51,9 +51,9 @@ func resourceConsulCertificateAuthorityCreate(d *schema.ResourceData, meta inter } func resourceConsulCertificateAuthorityRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Connect() + client, qOpts, _ := getClient(d, meta) - conf, _, err := client.CAGetConfig(nil) + conf, _, err := client.Connect().CAGetConfig(qOpts) if err != nil { return fmt.Errorf("Failed to get CA configuration: %v", err) } diff --git a/consul/resource_consul_config_entry.go b/consul/resource_consul_config_entry.go index 1d4d6ef7..c9378756 100644 --- a/consul/resource_consul_config_entry.go +++ b/consul/resource_consul_config_entry.go @@ -48,24 +48,20 @@ func resourceConsulConfigEntry() *schema.Resource { } func resourceConsulConfigEntryUpdate(d *schema.ResourceData, meta interface{}) error { - configEntries := getClient(meta).ConfigEntries() + client, qOpts, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() kind := d.Get("kind").(string) name := d.Get("name").(string) - namespace := getNamespace(d, meta) - configEntry, err := makeConfigEntry(kind, name, d.Get("config_json").(string), namespace) + configEntry, err := makeConfigEntry(kind, name, d.Get("config_json").(string), wOpts.Namespace) if err != nil { return err } - wOpts := &consulapi.WriteOptions{} if _, _, err := configEntries.Set(configEntry, wOpts); err != nil { return fmt.Errorf("Failed to set '%s' config entry: %v", name, err) } - qOpts := &consulapi.QueryOptions{ - Namespace: namespace, - } _, _, err = configEntries.Get(configEntry.GetKind(), configEntry.GetName(), qOpts) if err != nil { if strings.Contains(err.Error(), "Unexpected response code: 404") { @@ -82,14 +78,11 @@ to see what values are expected.`, configEntry.GetKind()) } func resourceConsulConfigEntryRead(d *schema.ResourceData, meta interface{}) error { - configEntries := getClient(meta).ConfigEntries() + client, qOpts, _ := getClient(d, meta) + configEntries := client.ConfigEntries() configKind := d.Get("kind").(string) configName := d.Get("name").(string) - namespace := getNamespace(d, meta) - qOpts := &consulapi.QueryOptions{ - Namespace: namespace, - } configEntry, _, err := configEntries.Get(configKind, configName, qOpts) if err != nil { if strings.Contains(err.Error(), "Unexpected response code: 404") { @@ -113,13 +106,11 @@ func resourceConsulConfigEntryRead(d *schema.ResourceData, meta interface{}) err } func resourceConsulConfigEntryDelete(d *schema.ResourceData, meta interface{}) error { - configEntries := getClient(meta).ConfigEntries() + client, _, wOpts := getClient(d, meta) + configEntries := client.ConfigEntries() configKind := d.Get("kind").(string) configName := d.Get("name").(string) - wOpts := &consulapi.WriteOptions{ - Namespace: getNamespace(d, meta), - } if _, err := configEntries.Delete(configKind, configName, wOpts); err != nil { return fmt.Errorf("Failed to delete '%s' config entry: %#v", configName, err) } diff --git a/consul/resource_consul_intention.go b/consul/resource_consul_intention.go index 8a0d1045..30591fc4 100644 --- a/consul/resource_consul_intention.go +++ b/consul/resource_consul_intention.go @@ -77,24 +77,17 @@ Please see https://registry.terraform.io/providers/hashicorp/consul/latest/docs/ } func resourceConsulIntentionCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) connect := client.Connect() - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - - wOpts := consulapi.WriteOptions{Datacenter: dc} - intention, err := getIntention(d) if err != nil { return err } - id, _, err := connect.IntentionCreate(intention, &wOpts) + id, _, err := connect.IntentionCreate(intention, wOpts) if err != nil { - return fmt.Errorf("Failed to create intention (dc: '%s'): %v", dc, err) + return fmt.Errorf("Failed to create intention (dc: '%s'): %v", wOpts.Datacenter, err) } d.SetId(id) @@ -103,44 +96,31 @@ func resourceConsulIntentionCreate(d *schema.ResourceData, meta interface{}) err } func resourceConsulIntentionUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) connect := client.Connect() - // Setup the operations using the datacenter - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - wOpts := consulapi.WriteOptions{Datacenter: dc} - intention, err := getIntention(d) if err != nil { return err } intention.ID = d.Id() - if _, err := connect.IntentionUpdate(intention, &wOpts); err != nil { - return fmt.Errorf("Failed to update intention (dc: '%s'): %v", dc, err) + if _, err := connect.IntentionUpdate(intention, wOpts); err != nil { + return fmt.Errorf("Failed to update intention (dc: '%s'): %v", wOpts.Datacenter, err) } return resourceConsulIntentionRead(d, meta) } func resourceConsulIntentionRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) connect := client.Connect() - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - id := d.Id() - qOpts := consulapi.QueryOptions{Datacenter: dc} - intention, _, err := connect.IntentionGet(id, &qOpts) + intention, _, err := connect.IntentionGet(id, qOpts) if err != nil { - return fmt.Errorf("Failed to retrieve intention (dc: '%s'): %v", dc, err) + return fmt.Errorf("Failed to retrieve intention (dc: '%s'): %v", qOpts.Datacenter, err) } if intention == nil { @@ -148,7 +128,7 @@ func resourceConsulIntentionRead(d *schema.ResourceData, meta interface{}) error return nil } - if err = d.Set("datacenter", dc); err != nil { + if err = d.Set("datacenter", qOpts.Datacenter); err != nil { return fmt.Errorf("failed to set 'datacenter': %v", err) } if err = d.Set("source_name", intention.SourceName); err != nil { @@ -177,21 +157,13 @@ func resourceConsulIntentionRead(d *schema.ResourceData, meta interface{}) error } func resourceConsulIntentionDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) connect := client.Connect() id := d.Id() - dc, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("Failed to get DC: %v", err) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{Datacenter: dc} - - if _, err := connect.IntentionDelete(id, &wOpts); err != nil { + if _, err := connect.IntentionDelete(id, wOpts); err != nil { return fmt.Errorf("Failed to delete intention with id '%s' in %s: %v", - id, dc, err) + id, wOpts.Datacenter, err) } // Clear the ID diff --git a/consul/resource_consul_intention_test.go b/consul/resource_consul_intention_test.go index 6c3a0e1a..dcc96dae 100644 --- a/consul/resource_consul_intention_test.go +++ b/consul/resource_consul_intention_test.go @@ -91,7 +91,7 @@ func TestAccConsulIntention_namespaceEE(t *testing.T) { } func testAccCheckConsulIntentionDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) qOpts := consulapi.QueryOptions{} intentions, _, err := client.Connect().Intentions(&qOpts) @@ -108,7 +108,7 @@ func testAccCheckConsulIntentionDestroy(s *terraform.State) error { func testAccRemoveConsulIntention(t *testing.T) func() { return func() { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) connect := client.Connect() qOpts := &consulapi.QueryOptions{} iM := &consulapi.IntentionMatch{ diff --git a/consul/resource_consul_key_prefix.go b/consul/resource_consul_key_prefix.go index 1aadb227..c0b6c143 100644 --- a/consul/resource_consul_key_prefix.go +++ b/consul/resource_consul_key_prefix.go @@ -83,16 +83,7 @@ func resourceConsulKeyPrefix() *schema.Resource { } func resourceConsulKeyPrefixCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) type subKey struct { value string @@ -149,7 +140,7 @@ func resourceConsulKeyPrefixCreate(d *schema.ResourceData, meta interface{}) err // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) // Now we can just write in all the initial values, since we can expect // that nothing should need deleting yet, as long as there isn't some @@ -167,16 +158,7 @@ func resourceConsulKeyPrefixCreate(d *schema.ResourceData, meta interface{}) err } func resourceConsulKeyPrefixUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) pathPrefix := d.Get("path_prefix").(string) @@ -274,22 +256,13 @@ func resourceConsulKeyPrefixUpdate(d *schema.ResourceData, meta interface{}) err // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) return nil } func resourceConsulKeyPrefixRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) pathPrefix := d.Get("path_prefix").(string) @@ -340,7 +313,7 @@ func resourceConsulKeyPrefixRead(d *schema.ResourceData, meta interface{}) error // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - if err := d.Set("datacenter", dc); err != nil { + if err := d.Set("datacenter", keyClient.qOpts.Datacenter); err != nil { return fmt.Errorf("failed to set 'datacenter': %v", err) } @@ -348,22 +321,13 @@ func resourceConsulKeyPrefixRead(d *schema.ResourceData, meta interface{}) error } func resourceConsulKeyPrefixDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) pathPrefix := d.Get("path_prefix").(string) // Delete everything under our prefix, since the entire set of keys under // the given prefix is considered to be managed exclusively by Terraform. - err = keyClient.DeleteUnderPrefix(pathPrefix) + err := keyClient.DeleteUnderPrefix(pathPrefix) if err != nil { return err } diff --git a/consul/resource_consul_key_prefix_test.go b/consul/resource_consul_key_prefix_test.go index 0636b3f1..baf0aa9d 100644 --- a/consul/resource_consul_key_prefix_test.go +++ b/consul/resource_consul_key_prefix_test.go @@ -66,7 +66,7 @@ func TestAccConsulKeyPrefix_basic(t *testing.T) { }, { PreConfig: func() { - kv := getClient(testAccProvider.Meta()).KV() + kv := getTestClient(testAccProvider.Meta()).KV() kv.DeleteTree("", nil) }, Config: testAccConsulKeyPrefixConfig_root, @@ -167,8 +167,21 @@ func TestAccConsulKeyPrefix_deleted(t *testing.T) { }) } +func TestAccConsulKeyPrefix_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccConsulKeyPrefixConfig_datacenter, + Check: testAccCheckConsulKeysDatacenter, + }, + }, + }) +} + func testAccCheckConsulKeyPrefixDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pair, _, err := kv.Get("test/set", opts) @@ -184,7 +197,7 @@ func testAccCheckConsulKeyPrefixDestroy(s *terraform.State) error { func testAccCheckConsulKeyPrefixKeyAbsent(name string) resource.TestCheckFunc { fullName := "prefix_test/" + name return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pair, _, err := kv.Get(fullName, opts) @@ -203,7 +216,7 @@ func testAccCheckConsulKeyPrefixKeyAbsent(name string) resource.TestCheckFunc { func testAccAddConsulKeyPrefixRogue(name, value string) resource.TestCheckFunc { fullName := "prefix_test/" + name return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.WriteOptions{Datacenter: "dc1"} pair := &consulapi.KVPair{ @@ -219,7 +232,7 @@ func testAccAddConsulKeyPrefixRogue(name, value string) resource.TestCheckFunc { // It removes the prefix_test "folder" (all keys under this prefix) func testAccDeleteConsulKeyPrefix(t *testing.T, prefix string) func() { return func() { - kv := getClient(testAccProvider.Meta()).KV() + kv := getTestClient(testAccProvider.Meta()).KV() _, err := kv.DeleteTree(prefix, &consulapi.WriteOptions{Datacenter: "dc1"}) if err != nil { t.Fatalf("failed to delete tree: %v", err) @@ -231,7 +244,7 @@ func testAccDeleteConsulKeyPrefix(t *testing.T, prefix string) func() { // It removes one key in Consul func testAccDeleteConsulKey(t *testing.T, key string) func() { return func() { - kv := getClient(testAccProvider.Meta()).KV() + kv := getTestClient(testAccProvider.Meta()).KV() _, err := kv.Delete(key, &consulapi.WriteOptions{Datacenter: "dc1"}) if err != nil { t.Fatalf("failed to delete key %q: %v", key, err) @@ -242,7 +255,7 @@ func testAccDeleteConsulKey(t *testing.T, key string) func() { func testAccCheckConsulKeyPrefixKeyValue(name, value string, flags uint64) resource.TestCheckFunc { fullName := "prefix_test/" + name return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pair, _, err := kv.Get(fullName, opts) @@ -373,6 +386,27 @@ resource "consul_key_prefix" "app" { } ` +const testAccConsulKeyPrefixConfig_datacenter = ` +resource "consul_key_prefix" "dc1" { + path_prefix = "foo/" + + subkey { + path = "dc" + value = "dc1" + } +} + +resource "consul_key_prefix" "dc2" { + datacenter = "dc2" + path_prefix = "foo/" + + subkey { + path = "dc" + value = "dc2" + } +} +` + const testAccConsulKeyPrefixConfig_root = ` resource "consul_key_prefix" "root" { path_prefix = "" diff --git a/consul/resource_consul_keys.go b/consul/resource_consul_keys.go index 1a58a444..0f1169ea 100644 --- a/consul/resource_consul_keys.go +++ b/consul/resource_consul_keys.go @@ -3,9 +3,7 @@ package consul import ( "fmt" "strconv" - "strings" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -102,16 +100,7 @@ func resourceConsulKeys() *schema.Resource { } func resourceConsulKeysCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) if d.HasChange("key") { o, n := d.GetChange("key") @@ -187,7 +176,7 @@ func resourceConsulKeysCreateUpdate(d *schema.ResourceData, meta interface{}) er // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) // The ID doesn't matter, since we use provider config, datacenter, // and key paths to address consul properly. So we just need to fill it in @@ -198,16 +187,7 @@ func resourceConsulKeysCreateUpdate(d *schema.ResourceData, meta interface{}) er } func resourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) vars := make(map[string]string) @@ -251,22 +231,13 @@ func resourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error { // Store the datacenter on this resource, which can be helpful for reference // in case it was read from the provider - d.Set("datacenter", dc) + d.Set("datacenter", keyClient.qOpts.Datacenter) return nil } func resourceConsulKeysDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - kv := client.KV() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - keyClient := newKeyClient(kv, dc, token, namespace) + keyClient := newKeyClient(d, meta) // Clean up any keys that we're explicitly managing keys := d.Get("key").(*schema.Set).List() @@ -329,24 +300,3 @@ func attributeValue(sub map[string]interface{}, readValue string) string { // No value return "" } - -// getDC is used to get the datacenter of the local agent -func getDC(d *schema.ResourceData, client *consulapi.Client, meta interface{}) (string, error) { - if v, ok := d.GetOk("datacenter"); ok { - return v.(string), nil - } - info, err := client.Agent().Self() - if err != nil { - datacenter := meta.(*Config).Datacenter - if datacenter != "" { - return datacenter, nil - } - // Reading can fail with `Unexpected response code: 403 (Permission denied)` - // if the permission has not been given. Default to "" in this case. - if strings.HasSuffix(err.Error(), "403 (Permission denied)") { - return "", nil - } - return "", fmt.Errorf("Failed to get datacenter from Consul agent: %v", err) - } - return info["Config"]["Datacenter"].(string), nil -} diff --git a/consul/resource_consul_keys_test.go b/consul/resource_consul_keys_test.go index 81702ec1..aaed43aa 100644 --- a/consul/resource_consul_keys_test.go +++ b/consul/resource_consul_keys_test.go @@ -76,26 +76,21 @@ func TestAccConsulKeys_NamespaceEE(t *testing.T) { }) } -func testAccCheckConsulKeysFlags(path string, flags int) resource.TestCheckFunc { - return func(s *terraform.State) error { - kv := testAccProvider.Meta().(*consulapi.Client).KV() - opts := &consulapi.QueryOptions{Datacenter: "dc1"} - pair, _, err := kv.Get(path, opts) - if err != nil { - return err - } - if pair == nil { - return fmt.Errorf("Key '%v' does not exist", path) - } - if int(pair.Flags) != flags { - return fmt.Errorf("Wrong flags for '%v': %v != %v", path, int(pair.Flags), flags) - } - return nil - } +func TestAccConsulKeys_Datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccConsulKeysDatacenter, + Check: testAccCheckConsulKeysDatacenter, + }, + }, + }) } func testAccCheckConsulKeysDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pair, _, err := kv.Get("test/set", opts) @@ -110,7 +105,7 @@ func testAccCheckConsulKeysDestroy(s *terraform.State) error { func testAccCheckConsulKeysExists() resource.TestCheckFunc { return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) kv := client.KV() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pair, _, err := kv.Get("test/set", opts) @@ -158,6 +153,32 @@ func testAccCheckConsulKeysRemoved(n, attr string) resource.TestCheckFunc { } } +func testAccCheckConsulKeysDatacenter(s *terraform.State) error { + test := func(dc string) error { + kv := getTestClient(testAccProvider.Meta()).KV() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + pair, _, err := kv.Get("foo/dc", opts) + if err != nil { + return err + } + if kv == nil { + return fmt.Errorf("key 'dc' does not exist") + } + value := string(pair.Value) + if value != dc { + return fmt.Errorf("wrong value: %q", value) + } + return nil + } + + if err := test("dc1"); err != nil { + return err + } + return test("dc2") +} + const testAccConsulKeysConfig = ` resource "consul_keys" "app" { datacenter = "dc1" @@ -228,8 +249,28 @@ resource "consul_keys" "consul" { namespace = consul_namespace.test.name key { - path = "test/set" - value = "" + path = "test/set" + value = "" delete = true } }` + +const testAccConsulKeysDatacenter = ` +resource "consul_keys" "dc1" { + key { + path = "foo/dc" + value = "dc1" + delete = true + } +} + +resource "consul_keys" "dc2" { + datacenter = "dc2" + + key { + path = "foo/dc" + value = "dc2" + delete = true + } +} +` diff --git a/consul/resource_consul_license.go b/consul/resource_consul_license.go index b8f98ee7..5eda10d0 100644 --- a/consul/resource_consul_license.go +++ b/consul/resource_consul_license.go @@ -3,7 +3,6 @@ package consul import ( "fmt" - consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -82,20 +81,12 @@ func resourceConsulLicense() *schema.Resource { } func resourceConsulLicenseCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() license := d.Get("license").(string) - datacenter, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("failed to read datacenter: %v", err) - } - - wOpts := &consulapi.WriteOptions{ - Datacenter: datacenter, - } - _, err = operator.LicensePut(license, wOpts) + _, err := operator.LicensePut(license, wOpts) if err != nil { return fmt.Errorf("failed to set license: %v", err) } @@ -104,18 +95,9 @@ func resourceConsulLicenseCreate(d *schema.ResourceData, meta interface{}) error } func resourceConsulLicenseRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() - datacenter, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("failed to read datacenter: %v", err) - } - - qOpts := &consulapi.QueryOptions{ - Datacenter: datacenter, - } - licenseReply, err := operator.LicenseGet(qOpts) if err != nil { return fmt.Errorf("failed to read license: %v", err) @@ -139,19 +121,10 @@ func resourceConsulLicenseRead(d *schema.ResourceData, meta interface{}) error { } func resourceConsulLicenseDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() - datacenter, err := getDC(d, client, meta) - if err != nil { - return fmt.Errorf("failed to read datacenter: %v", err) - } - - wOpts := &consulapi.WriteOptions{ - Datacenter: datacenter, - } - - _, err = operator.LicenseReset(wOpts) + _, err := operator.LicenseReset(wOpts) if err != nil { return fmt.Errorf("failed to remove license: %v", err) } diff --git a/consul/resource_consul_license_test.go b/consul/resource_consul_license_test.go index 88210a6f..2d0b395e 100644 --- a/consul/resource_consul_license_test.go +++ b/consul/resource_consul_license_test.go @@ -3,7 +3,6 @@ package consul import ( "os" "regexp" - "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -58,31 +57,6 @@ func TestAccConsulLicense_CorrectLicense(t *testing.T) { }) } -func serverIsConsulCommunityEdition(t *testing.T) bool { - client := getClient(testAccProvider.Meta()) - self, err := client.Agent().Self() - if err != nil { - t.Fatalf("failed to get agent information: %v", err) - } - return !strings.HasSuffix(self["Config"]["Version"].(string), "+ent") -} - -func skipTestOnConsulCommunityEdition(t *testing.T) { - testAccPreCheck(t) - - if serverIsConsulCommunityEdition(t) { - t.Skip("Test skipped on Consul Community Edition. Use a Consul Enterprise server to run this test.") - } -} - -func skipTestOnConsulEnterpriseEdition(t *testing.T) { - testAccPreCheck(t) - - if !serverIsConsulCommunityEdition(t) { - t.Skip("Test skipped on Consul Enterprise Edition. Use a Consul Community server to run this test.") - } -} - const testAccConsulLicense = ` resource "consul_license" "license" { license = "foobar" diff --git a/consul/resource_consul_namespace.go b/consul/resource_consul_namespace.go index 36ff61be..a9efd4e5 100644 --- a/consul/resource_consul_namespace.go +++ b/consul/resource_consul_namespace.go @@ -46,11 +46,10 @@ func resourceConsulNamespace() *schema.Resource { } func resourceConsulNamespaceCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Namespaces() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) namespace := getNamespaceFromResourceData(d) - namespace, _, err := client.Create(namespace, wOpts) + namespace, _, err := client.Namespaces().Create(namespace, wOpts) if err != nil { return fmt.Errorf("failed to create namespace: %v", err) } @@ -59,11 +58,10 @@ func resourceConsulNamespaceCreate(d *schema.ResourceData, meta interface{}) err } func resourceConsulNamespaceRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Namespaces() - qOpts := &consulapi.QueryOptions{} + client, qOpts, _ := getClient(d, meta) name := d.Id() - namespace, _, err := client.Read(name, qOpts) + namespace, _, err := client.Namespaces().Read(name, qOpts) if namespace == nil { d.SetId("") return nil @@ -97,11 +95,10 @@ func resourceConsulNamespaceRead(d *schema.ResourceData, meta interface{}) error } func resourceConsulNamespaceUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Namespaces() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) namespace := getNamespaceFromResourceData(d) - namespace, _, err := client.Update(namespace, wOpts) + namespace, _, err := client.Namespaces().Update(namespace, wOpts) if err != nil { return fmt.Errorf("failed to update namespace '%s': %v", namespace.Name, err) } @@ -110,10 +107,9 @@ func resourceConsulNamespaceUpdate(d *schema.ResourceData, meta interface{}) err } func resourceConsulNamespaceDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta).Namespaces() - wOpts := &consulapi.WriteOptions{} + client, _, wOpts := getClient(d, meta) - _, err := client.Delete(d.Id(), wOpts) + _, err := client.Namespaces().Delete(d.Id(), wOpts) if err != nil { return fmt.Errorf("failed to delete namespace '%s': %v", d.Id(), err) } diff --git a/consul/resource_consul_network_area.go b/consul/resource_consul_network_area.go index 1811fe9f..19c23f99 100644 --- a/consul/resource_consul_network_area.go +++ b/consul/resource_consul_network_area.go @@ -50,7 +50,7 @@ func resourceConsulNetworkArea() *schema.Resource { } func resourceConsulNetworkAreaCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() area := &consulapi.Area{ @@ -67,16 +67,6 @@ func resourceConsulNetworkAreaCreate(d *schema.ResourceData, meta interface{}) e area.RetryJoin = s } - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - wOpts := &consulapi.WriteOptions{ - Token: token, - Datacenter: dc, - } id, _, err := operator.AreaCreate(area, wOpts) if err != nil { return fmt.Errorf("Failed to create network area: %v", err) @@ -87,21 +77,11 @@ func resourceConsulNetworkAreaCreate(d *schema.ResourceData, meta interface{}) e } func resourceConsulNetworkAreaRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) operator := client.Operator() id := d.Id() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - qOpts := &consulapi.QueryOptions{ - Token: token, - Datacenter: dc, - } area, _, err := operator.AreaGet(id, qOpts) if err != nil { return fmt.Errorf("Failed to get %s area: %v", id, err) @@ -134,7 +114,7 @@ func resourceConsulNetworkAreaRead(d *schema.ResourceData, meta interface{}) err } func resourceConsulNetworkAreaUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() id := d.Id() @@ -157,16 +137,6 @@ func resourceConsulNetworkAreaUpdate(d *schema.ResourceData, meta interface{}) e area.RetryJoin = s } - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - wOpts := &consulapi.WriteOptions{ - Token: token, - Datacenter: dc, - } _id, _, err := operator.AreaUpdate(id, area, wOpts) if err != nil { return fmt.Errorf("Failed to update '%s' network area: %v", id, err) @@ -181,22 +151,12 @@ func resourceConsulNetworkAreaUpdate(d *schema.ResourceData, meta interface{}) e } func resourceConsulNetworkAreaDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) operator := client.Operator() id := d.Id() - token := d.Get("token").(string) - dc, err := getDC(d, client, meta) - if err != nil { - return err - } - - wOpts := &consulapi.WriteOptions{ - Token: token, - Datacenter: dc, - } - _, err = operator.AreaDelete(id, wOpts) + _, err := operator.AreaDelete(id, wOpts) if err != nil { return fmt.Errorf("Failed to delete '%s' network area: %v", err, id) } diff --git a/consul/resource_consul_network_area_test.go b/consul/resource_consul_network_area_test.go index a17276d9..61a20d3e 100644 --- a/consul/resource_consul_network_area_test.go +++ b/consul/resource_consul_network_area_test.go @@ -59,8 +59,64 @@ func TestAccConsulNetworkArea_CommunityEdition(t *testing.T) { }) } +func TestAccConsulNetworkArea_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccRemoteDatacenterPreCheck(t) + skipTestOnConsulCommunityEdition(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccConsulNetworkAreaCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConsulNetworkAreaDatacenter, + Check: func(s *terraform.State) error { + test := func(dc, peer string) error { + c := getTestClient(testAccProvider.Meta()).Operator() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + area, _, err := c.AreaList(opts) + if err != nil { + return err + } + if len(area) != 1 { + return fmt.Errorf("wrong number of network area: %#v", area) + } + if area[0].PeerDatacenter != peer { + return fmt.Errorf("unexpected peer: %s", area[0].PeerDatacenter) + } + return nil + } + if err := test("dc1", "dc2"); err != nil { + return err + } + return test("dc2", "dc1") + }, + }, + { + Config: testAccConsulNetworkAreaBasic_update1, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_network_area.test", "peer_datacenter", "foo"), + resource.TestCheckResourceAttr("consul_network_area.test", "use_tls", "true"), + resource.TestCheckResourceAttr("consul_network_area.test", "retry_join.#", "1"), + resource.TestCheckResourceAttr("consul_network_area.test", "retry_join.0", "1.2.3.4"), + ), + }, + { + Config: testAccConsulNetworkAreaBasic_update2, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_network_area.test", "peer_datacenter", "bar"), + resource.TestCheckResourceAttr("consul_network_area.test", "use_tls", "true"), + resource.TestCheckResourceAttr("consul_network_area.test", "retry_join.#", "0"), + ), + }, + }, + }) +} + func testAccConsulNetworkAreaCheckDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) operator := client.Operator() qOpts := &consulapi.QueryOptions{} @@ -100,3 +156,16 @@ resource "consul_network_area" "test" { use_tls = true } ` + +const testAccConsulNetworkAreaDatacenter = ` +resource "consul_network_area" "dc1" { + peer_datacenter = "dc2" + retry_join = [] +} + +resource "consul_network_area" "dc2" { + datacenter = "dc2" + peer_datacenter = "dc1" + retry_join = [] +} +` diff --git a/consul/resource_consul_node.go b/consul/resource_consul_node.go index 4212a713..e6a19cf1 100644 --- a/consul/resource_consul_node.go +++ b/consul/resource_consul_node.go @@ -53,33 +53,15 @@ func resourceConsulNode() *schema.Resource { } func resourceConsulNodeCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, wOpts := getClient(d, meta) catalog := client.Catalog() - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } else { - var err error - if dc, err = getDC(d, client, meta); err != nil { - return err - } - } - - var token string - if v, ok := d.GetOk("token"); ok { - token = v.(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token} - address := d.Get("address").(string) name := d.Get("name").(string) registration := &consulapi.CatalogRegistration{ Address: address, - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: name, } @@ -91,18 +73,17 @@ func resourceConsulNodeCreate(d *schema.ResourceData, meta interface{}) error { registration.NodeMeta = nodeMeta } - if _, err := catalog.Register(registration, &wOpts); err != nil { + if _, err := catalog.Register(registration, wOpts); err != nil { return fmt.Errorf("Failed to register Consul catalog node with name '%s' at address '%s' in %s: %v", - name, address, dc, err) + name, address, wOpts.Datacenter, err) } // Update the resource - qOpts := consulapi.QueryOptions{Datacenter: dc} - if _, _, err := catalog.Node(name, &qOpts); err != nil { + if _, _, err := catalog.Node(name, qOpts); err != nil { return fmt.Errorf("Failed to read Consul catalog node with name '%s' at address '%s' in %s: %v", - name, address, dc, err) + name, address, qOpts.Datacenter, err) } else { - d.Set("datacenter", dc) + d.Set("datacenter", qOpts.Datacenter) } d.SetId(fmt.Sprintf("%s-%s", name, address)) @@ -111,21 +92,12 @@ func resourceConsulNodeCreate(d *schema.ResourceData, meta interface{}) error { } func resourceConsulNodeRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, qOpts, _ := getClient(d, meta) catalog := client.Catalog() - // Get the DC, error if not available. - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } - name := d.Get("name").(string) - // Setup the operations using the datacenter - qOpts := consulapi.QueryOptions{Datacenter: dc} - - n, _, err := catalog.Node(name, &qOpts) + n, _, err := catalog.Node(name, qOpts) if err != nil { return fmt.Errorf("Failed to get name '%s' from Consul catalog: %v", name, err) } @@ -145,39 +117,21 @@ func resourceConsulNodeRead(d *schema.ResourceData, meta interface{}) error { } func resourceConsulNodeDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) + client, _, wOpts := getClient(d, meta) catalog := client.Catalog() - var dc string - if v, ok := d.GetOk("datacenter"); ok { - dc = v.(string) - } else { - var err error - if dc, err = getDC(d, client, meta); err != nil { - return err - } - } - - var token string - if v, ok := d.GetOk("token"); ok { - token = v.(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token} - address := d.Get("address").(string) name := d.Get("name").(string) deregistration := consulapi.CatalogDeregistration{ Address: address, - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: name, } - if _, err := catalog.Deregister(&deregistration, &wOpts); err != nil { + if _, err := catalog.Deregister(&deregistration, wOpts); err != nil { return fmt.Errorf("Failed to deregister Consul catalog node with name '%s' at address '%s' in %s: %v", - name, address, dc, err) + name, address, wOpts.Datacenter, err) } // Clear the ID diff --git a/consul/resource_consul_node_test.go b/consul/resource_consul_node_test.go index 8505d0ab..033d2a0a 100644 --- a/consul/resource_consul_node_test.go +++ b/consul/resource_consul_node_test.go @@ -82,8 +82,44 @@ func TestAccConsulNode_nodeMeta(t *testing.T) { }) } +func TestAccConsulNode_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckConsulNodeDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConsulNodeConfigDatacenter, + Check: func(s *terraform.State) error { + test := func(dc string) error { + c := getTestClient(testAccProvider.Meta()).Catalog() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + nodes, _, err := c.Nodes(opts) + if err != nil { + return err + } + + for _, n := range nodes { + if n.Node == dc { + return nil + } + } + return fmt.Errorf("could not find node %q", dc) + } + if err := test("dc1"); err != nil { + return err + } + return test("dc2") + }, + }, + }, + }) +} + func testAccCheckConsulNodeDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() qOpts := consulapi.QueryOptions{} nodes, _, err := catalog.Nodes(&qOpts) @@ -100,7 +136,7 @@ func testAccCheckConsulNodeDestroy(s *terraform.State) error { func testAccCheckConsulNodeExists() resource.TestCheckFunc { return func(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() qOpts := consulapi.QueryOptions{} nodes, _, err := catalog.Nodes(&qOpts) @@ -152,7 +188,7 @@ func testAccCheckConsulNodeValueRemoved(n, attr string) resource.TestCheckFunc { func testAccRemoveConsulNode(t *testing.T) func() { return func() { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() wOpts := &consulapi.WriteOptions{} dereg := &consulapi.CatalogDeregistration{ @@ -167,7 +203,7 @@ func testAccRemoveConsulNode(t *testing.T) func() { func testAccChangeConsulNodeAddress(t *testing.T) func() { return func() { - catalog := getClient(testAccProvider.Meta()).Catalog() + catalog := getTestClient(testAccProvider.Meta()).Catalog() wOpts := &consulapi.WriteOptions{} registration := &consulapi.CatalogRegistration{ @@ -186,7 +222,7 @@ func testAccChangeConsulNodeAddress(t *testing.T) func() { } func testAccChangeConsulNodeAddressMeta(t *testing.T) func() { return func() { - catalog := getClient(testAccProvider.Meta()).Catalog() + catalog := getTestClient(testAccProvider.Meta()).Catalog() wOpts := &consulapi.WriteOptions{} registration := &consulapi.CatalogRegistration{ @@ -202,7 +238,7 @@ func testAccChangeConsulNodeAddressMeta(t *testing.T) func() { } func testAccConsulNodeDetectAttributeChanges(*terraform.State) error { - catalog := getClient(testAccProvider.Meta()).Catalog() + catalog := getTestClient(testAccProvider.Meta()).Catalog() n, _, err := catalog.Node("foo", &consulapi.QueryOptions{}) if err != nil { return fmt.Errorf("Failed to read 'foo': %v", err) @@ -254,3 +290,16 @@ resource "consul_node" "foo" { } } ` + +const testAccConsulNodeConfigDatacenter = ` +resource "consul_node" "dc1" { + name = "dc1" + address = "127.0.0.1" +} + +resource "consul_node" "dc2" { + datacenter = "dc2" + name = "dc2" + address = "127.0.0.1" +} +` diff --git a/consul/resource_consul_prepared_query.go b/consul/resource_consul_prepared_query.go index 1b201d12..4b05fabd 100644 --- a/consul/resource_consul_prepared_query.go +++ b/consul/resource_consul_prepared_query.go @@ -146,15 +146,10 @@ func resourceConsulPreparedQuery() *schema.Resource { } func resourceConsulPreparedQueryCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - wo := &consulapi.WriteOptions{ - Datacenter: d.Get("datacenter").(string), - Token: d.Get("token").(string), - } - + client, _, wOpts := getClient(d, meta) pq := preparedQueryDefinitionFromResourceData(d) - id, _, err := client.PreparedQuery().Create(pq, wo) + id, _, err := client.PreparedQuery().Create(pq, wOpts) if err != nil { return err } @@ -164,15 +159,10 @@ func resourceConsulPreparedQueryCreate(d *schema.ResourceData, meta interface{}) } func resourceConsulPreparedQueryUpdate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - wo := &consulapi.WriteOptions{ - Datacenter: d.Get("datacenter").(string), - Token: d.Get("token").(string), - } - + client, _, wOpts := getClient(d, meta) pq := preparedQueryDefinitionFromResourceData(d) - if _, err := client.PreparedQuery().Update(pq, wo); err != nil { + if _, err := client.PreparedQuery().Update(pq, wOpts); err != nil { return err } @@ -180,13 +170,9 @@ func resourceConsulPreparedQueryUpdate(d *schema.ResourceData, meta interface{}) } func resourceConsulPreparedQueryRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - qo := &consulapi.QueryOptions{ - Datacenter: d.Get("datacenter").(string), - Token: d.Get("token").(string), - } + client, qOpts, _ := getClient(d, meta) - queries, _, err := client.PreparedQuery().Get(d.Id(), qo) + queries, _, err := client.PreparedQuery().Get(d.Id(), qOpts) if err != nil { // Check for a 404/not found, these are returned as errors. if strings.Contains(err.Error(), "not found") { @@ -290,13 +276,9 @@ func resourceConsulPreparedQueryRead(d *schema.ResourceData, meta interface{}) e } func resourceConsulPreparedQueryDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - writeOpts := &consulapi.WriteOptions{ - Datacenter: d.Get("datacenter").(string), - Token: d.Get("token").(string), - } + client, _, wOpts := getClient(d, meta) - if _, err := client.PreparedQuery().Delete(d.Id(), writeOpts); err != nil { + if _, err := client.PreparedQuery().Delete(d.Id(), wOpts); err != nil { return err } diff --git a/consul/resource_consul_prepared_query_test.go b/consul/resource_consul_prepared_query_test.go index 9be162da..83b24395 100644 --- a/consul/resource_consul_prepared_query_test.go +++ b/consul/resource_consul_prepared_query_test.go @@ -106,10 +106,10 @@ func TestAccConsulPreparedQuery_import(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckConsulPreparedQueryDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccConsulPreparedQueryConfig, }, - resource.TestStep{ + { ResourceName: "consul_prepared_query.foo", ImportState: true, ImportStateCheck: checkFn, @@ -123,22 +123,58 @@ func TestAccConsulPreparedQuery_blocks(t *testing.T) { PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccConsulPreparedQueryBlocks, }, - resource.TestStep{ + { Config: testAccConsulPreparedQueryBlocks2, }, - resource.TestStep{ + { Config: testAccConsulPreparedQueryBlocks3, }, - resource.TestStep{ + { Config: testAccConsulPreparedQueryBlocks4, }, }, }) } +func TestAccConsulPreparedQuery_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccConsulPreparedQueryDatacenter, + Check: func(s *terraform.State) error { + test := func(dc string) error { + c := getTestClient(testAccProvider.Meta()).PreparedQuery() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + pq, _, err := c.List(opts) + if err != nil { + return err + } + + if len(pq) != 1 { + return fmt.Errorf("wrong number of prepared queries: %#v", pq) + } + if pq[0].Name != dc { + return fmt.Errorf("unknown prepared query %q in datacenter %q", pq[0].Name, dc) + } + return nil + } + if err := test("dc1"); err != nil { + return err + } + return test("dc2") + }, + }, + }, + }) +} + func getPreparedQuery(s *terraform.State) (*api.PreparedQueryDefinition, error) { rn, ok := s.RootModule().Resources["consul_prepared_query.foo"] if !ok { @@ -146,7 +182,7 @@ func getPreparedQuery(s *terraform.State) (*api.PreparedQueryDefinition, error) } id := rn.Primary.ID - c := getClient(testAccProvider.Meta()) + c := getTestClient(testAccProvider.Meta()) client := c.PreparedQuery() opts := &consulapi.QueryOptions{Datacenter: "dc1"} pq, _, err := client.Get(id, opts) @@ -207,7 +243,7 @@ func testAccCheckConsulPreparedQueryExists() resource.TestCheckFunc { func testAccConsulPreparedQueryNearestN(t *testing.T) func() { return func() { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) wOpts := &consulapi.WriteOptions{} qOpts := &consulapi.QueryOptions{} @@ -360,3 +396,16 @@ resource "consul_prepared_query" "foo" { } } ` + +const testAccConsulPreparedQueryDatacenter = ` +resource "consul_prepared_query" "dc1" { + name = "dc1" + service = "redis" +} + +resource "consul_prepared_query" "dc2" { + datacenter = "dc2" + name = "dc2" + service = "redis" +} +` diff --git a/consul/resource_consul_service.go b/consul/resource_consul_service.go index 4e39a665..8d014429 100644 --- a/consul/resource_consul_service.go +++ b/consul/resource_consul_service.go @@ -13,11 +13,11 @@ import ( var headerResource = &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, }, - "value": &schema.Schema{ + "value": { Type: schema.TypeList, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -191,36 +191,24 @@ func resourceConsulService() *schema.Resource { } func resourceConsulServiceCreate(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) + client, qOpts, wOpts := getClient(d, meta) catalog := client.Catalog() name := d.Get("name").(string) node := d.Get("node").(string) - dc := "" - if _, ok := d.GetOk("datacenter"); ok { - dc = d.Get("datacenter").(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{ - Datacenter: dc, - Namespace: namespace, - } - - registration, ident, err := getCatalogRegistration(d, meta, dc) + registration, ident, err := getCatalogRegistration(d, meta) if err != nil { return err } - if _, err := catalog.Register(registration, &wOpts); err != nil { - return fmt.Errorf("Failed to register service (dc: '%s'): %v", dc, err) + if _, err := catalog.Register(registration, wOpts); err != nil { + return fmt.Errorf("Failed to register service (dc: '%s'): %v", wOpts.Datacenter, err) } // Retrieve the service again to get the canonical service ID. We can't // get this back from the register call or through - service, err := retrieveService(client, name, ident, node, dc, namespace) + service, err := retrieveService(client, name, ident, node, qOpts) if err != nil { return fmt.Errorf("Failed to retrieve service '%s' after registration. This may mean that the service should be manually deregistered. %v", ident, err) } @@ -231,46 +219,29 @@ func resourceConsulServiceCreate(d *schema.ResourceData, meta interface{}) error } func resourceConsulServiceUpdate(d *schema.ResourceData, meta interface{}) error { - catalog := getClient(meta).Catalog() - namespace := getNamespace(d, meta) - - dc := "" - if _, ok := d.GetOk("datacenter"); ok { - dc = d.Get("datacenter").(string) - } - - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{ - Datacenter: dc, - Namespace: namespace, - } + client, _, wOpts := getClient(d, meta) + catalog := client.Catalog() - registration, _, err := getCatalogRegistration(d, meta, dc) + registration, _, err := getCatalogRegistration(d, meta) if err != nil { return err } - if _, err := catalog.Register(registration, &wOpts); err != nil { - return fmt.Errorf("Failed to update service (dc: '%s'): %v", dc, err) + if _, err := catalog.Register(registration, wOpts); err != nil { + return fmt.Errorf("Failed to update service (dc: '%s'): %v", wOpts.Datacenter, err) } return resourceConsulServiceRead(d, meta) } func resourceConsulServiceRead(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) - - dc := "" - if _, ok := d.GetOk("datacenter"); ok { - dc = d.Get("datacenter").(string) - } + client, qOpts, _ := getClient(d, meta) id := d.Id() name := d.Get("name").(string) node := d.Get("node").(string) - service, err := retrieveService(client, name, id, node, dc, namespace) + service, err := retrieveService(client, name, id, node, qOpts) if err != nil { if err == NoServiceRegistered { d.SetId("") @@ -359,44 +330,26 @@ func resourceConsulServiceRead(d *schema.ResourceData, meta interface{}) error { } func resourceConsulServiceDelete(d *schema.ResourceData, meta interface{}) error { - client := getClient(meta) - namespace := getNamespace(d, meta) + client, _, wOpts := getClient(d, meta) catalog := client.Catalog() id := d.Id() node := d.Get("node").(string) - dc := "" - if _, ok := d.GetOk("datacenter"); ok { - dc = d.Get("datacenter").(string) - } - - var token string - if v, ok := d.GetOk("token"); ok { - token = v.(string) - } - // If we specified a custom service_id, we need // to utilize it for the delete if serviceID, ok := d.GetOk("service_id"); ok { id = serviceID.(string) } - // Setup the operations using the datacenter - wOpts := consulapi.WriteOptions{ - Datacenter: dc, - Token: token, - Namespace: namespace, - } - deregistration := consulapi.CatalogDeregistration{ - Datacenter: dc, + Datacenter: wOpts.Datacenter, Node: node, ServiceID: id, } - if _, err := catalog.Deregister(&deregistration, &wOpts); err != nil { + if _, err := catalog.Deregister(&deregistration, wOpts); err != nil { return fmt.Errorf("Failed to deregister Consul service with id '%s' in %s: %v", - id, dc, err) + id, wOpts.Datacenter, err) } // Clear the ID @@ -404,12 +357,8 @@ func resourceConsulServiceDelete(d *schema.ResourceData, meta interface{}) error return nil } -func retrieveService(client *consulapi.Client, name, ident, node, dc, namespace string) (*consulapi.CatalogService, error) { - qOpts := consulapi.QueryOptions{ - Datacenter: dc, - Namespace: namespace, - } - services, _, err := client.Catalog().Service(name, "", &qOpts) +func retrieveService(client *consulapi.Client, name, ident, node string, qOpts *consulapi.QueryOptions) (*consulapi.CatalogService, error) { + services, _, err := client.Catalog().Service(name, "", qOpts) if err != nil { return nil, err } @@ -418,7 +367,7 @@ func retrieveService(client *consulapi.Client, name, ident, node, dc, namespace for _, s := range services { if (s.ServiceID == ident) && (s.Node == node) { // Fetch health-checks for this service - healthChecks, _, err := client.Health().Checks(name, &qOpts) + healthChecks, _, err := client.Health().Checks(name, qOpts) if err != nil { return nil, fmt.Errorf("Failed to fetch health-checks: %v", err) } @@ -523,8 +472,8 @@ func parseHeaders(check map[string]interface{}) (map[string][]string, error) { return headers, nil } -func getCatalogRegistration(d *schema.ResourceData, meta interface{}, dc string) (*consulapi.CatalogRegistration, string, error) { - client := getClient(meta) +func getCatalogRegistration(d *schema.ResourceData, meta interface{}) (*consulapi.CatalogRegistration, string, error) { + client, qOpts, _ := getClient(d, meta) name := d.Get("name").(string) node := d.Get("node").(string) @@ -536,7 +485,7 @@ func getCatalogRegistration(d *schema.ResourceData, meta interface{}, dc string) // them to exist either ensures that it is knowlingly tracked // outside of TF state or that it is referencing a node // managed by the consul_node resource (or datasource) - nodeCheck, _, err := client.Catalog().Node(node, &consulapi.QueryOptions{Datacenter: dc}) + nodeCheck, _, err := client.Catalog().Node(node, qOpts) if err != nil { return nil, "", fmt.Errorf("Cannot retrieve node '%s': %v", node, err) } @@ -545,7 +494,7 @@ func getCatalogRegistration(d *schema.ResourceData, meta interface{}, dc string) } registration := &consulapi.CatalogRegistration{ - Datacenter: dc, + Datacenter: qOpts.Datacenter, Node: node, Service: &consulapi.AgentService{ Service: name, diff --git a/consul/resource_consul_service_test.go b/consul/resource_consul_service_test.go index 5645dd44..c5791994 100644 --- a/consul/resource_consul_service_test.go +++ b/consul/resource_consul_service_test.go @@ -256,8 +256,48 @@ func TestAccConsulService_NamespaceEE(t *testing.T) { }) } +func TestAccConsulService_datacenter(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccRemoteDatacenterPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccConsulServiceDatacenter, + Check: func(s *terraform.State) error { + test := func(dc string, expected bool) error { + c := getTestClient(testAccProvider.Meta()).Catalog() + opts := &consulapi.QueryOptions{ + Datacenter: dc, + } + svc, _, err := c.Services(opts) + if err != nil { + return err + } + + var found bool + for s := range svc { + if s == "test" { + found = true + } + } + if found != expected { + return fmt.Errorf("unexpected result: %v, %v", found, expected) + } + return nil + } + + if err := test("dc1", false); err != nil { + return err + } + return test("dc2", true) + }, + }, + }, + }) +} + func testAccConsulExternalSource(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) qOpts := consulapi.QueryOptions{} service, _, err := client.Catalog().Service("example", "", &qOpts) @@ -275,7 +315,7 @@ func testAccConsulExternalSource(s *terraform.State) error { } func testAccCheckConsulServiceDestroy(s *terraform.State) error { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) qOpts := consulapi.QueryOptions{} services, _, err := client.Catalog().Services(&qOpts) if err != nil { @@ -291,7 +331,7 @@ func testAccCheckConsulServiceDestroy(s *terraform.State) error { func testAccRemoveConsulService(t *testing.T, node, serviceID string) func() { return func() { - client := getClient(testAccProvider.Meta()) + client := getTestClient(testAccProvider.Meta()) catalog := client.Catalog() wOpts := &consulapi.WriteOptions{} dereg := &consulapi.CatalogDeregistration{ @@ -688,3 +728,18 @@ data "consul_service" "test" { } } ` + +const testAccConsulServiceDatacenter = ` +resource "consul_node" "test" { + datacenter = "dc2" + name = "test" + address = "test.com" +} + +resource "consul_service" "test" { + datacenter = "dc2" + name = "test" + node = consul_node.test.name + port = 80 +} +` diff --git a/consul/resource_provider.go b/consul/resource_provider.go index 405e528b..5a2a4767 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -179,16 +179,47 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { return config, nil } -func getClient(meta interface{}) *consulapi.Client { - return meta.(*Config).client -} +func getClient(d *schema.ResourceData, meta interface{}) (*consulapi.Client, *consulapi.QueryOptions, *consulapi.WriteOptions) { + client := getTestClient(meta) + var dc, token, namespace string + if v, ok := d.GetOk("datacenter"); ok { + dc = v.(string) + } + if v, ok := d.GetOk("namespace"); ok { + namespace = v.(string) + } + if v, ok := d.GetOk("token"); ok { + token = v.(string) + } -func getNamespace(d *schema.ResourceData, meta interface{}) string { - namespace := d.Get("namespace").(string) - if namespace != "" { - return namespace + if dc == "" { + if meta.(*Config).Datacenter != "" { + dc = meta.(*Config).Datacenter + } else { + info, _ := client.Agent().Self() + if info != nil { + dc = info["Config"]["Datacenter"].(string) + } + } } - return meta.(*Config).Namespace + + qOpts := &consulapi.QueryOptions{ + Datacenter: dc, + Namespace: namespace, + Token: token, + } + wOpts := &consulapi.WriteOptions{ + Datacenter: dc, + Namespace: namespace, + Token: token, + } + return client, qOpts, wOpts +} + +// during the tests we only have access to the definition of the provider, not +// the ResourceData +func getTestClient(meta interface{}) *consulapi.Client { + return meta.(*Config).client } type stateWriter struct { diff --git a/consul/resource_provider_test.go b/consul/resource_provider_test.go index 58cfa895..7aa8335b 100644 --- a/consul/resource_provider_test.go +++ b/consul/resource_provider_test.go @@ -3,6 +3,7 @@ package consul import ( "io/ioutil" "os" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -186,11 +187,44 @@ func TestResourceProvider_ConfigureTLSInsecureHttpsMismatch(t *testing.T) { // } func testAccPreCheck(t *testing.T) { - if v := os.Getenv("CONSUL_HTTP_ADDR"); v != "" { + if os.Getenv("CONSUL_HTTP_ADDR") != "" { return } - if v := os.Getenv("CONSUL_ADDRESS"); v != "" { + if os.Getenv("CONSUL_ADDRESS") != "" { return } t.Fatal("Either CONSUL_ADDRESS or CONSUL_HTTP_ADDR must be set for acceptance tests") } + +func testAccRemoteDatacenterPreCheck(t *testing.T) { + testAccPreCheck(t) + + if os.Getenv("TEST_REMOTE_DATACENTER") == "" { + t.Skip("Test skipped. Set TEST_REMOTE_DATACENTER to run this test.") + } +} + +func serverIsConsulCommunityEdition(t *testing.T) bool { + client := getTestClient(testAccProvider.Meta()) + self, err := client.Agent().Self() + if err != nil { + t.Fatalf("failed to get agent information: %v", err) + } + return !strings.HasSuffix(self["Config"]["Version"].(string), "+ent") +} + +func skipTestOnConsulCommunityEdition(t *testing.T) { + testAccPreCheck(t) + + if serverIsConsulCommunityEdition(t) { + t.Skip("Test skipped on Consul Community Edition. Use a Consul Enterprise server to run this test.") + } +} + +func skipTestOnConsulEnterpriseEdition(t *testing.T) { + testAccPreCheck(t) + + if !serverIsConsulCommunityEdition(t) { + t.Skip("Test skipped on Consul Enterprise Edition. Use a Consul Community server to run this test.") + } +} diff --git a/consul_test.hcl b/consul_test.hcl index 41008cc1..b9df4e29 100644 --- a/consul_test.hcl +++ b/consul_test.hcl @@ -1,4 +1,5 @@ ui = true +primary_datacenter = "dc1" limits = { http_max_conns_per_client = -1 @@ -13,3 +14,5 @@ acl = { master = "master-token" } } + +retry_join_wan = ["127.0.0.1:8307"] diff --git a/consul_test_dc2.hcl b/consul_test_dc2.hcl new file mode 100644 index 00000000..0b75cde7 --- /dev/null +++ b/consul_test_dc2.hcl @@ -0,0 +1,26 @@ +ui = true +datacenter = "dc2" +primary_datacenter = "dc1" + +limits = { + http_max_conns_per_client = -1 +} + +acl = { + enabled = true + default_policy = "allow" + down_policy = "extend-cache" + + tokens = { + replication = "master-token" + } +} + +ports = { + dns = -1 + grpc = -1 + http = 8501 + server = 8305 + serf_lan = 8306 + serf_wan = 8307 +}