Skip to content

Commit

Permalink
r/aws_elasticsearch_domain: Add custom endpoint support (#16192)
Browse files Browse the repository at this point in the history
Output from acceptance testing:

```
--- PASS: TestAccAWSElasticSearchDomain_AdvancedSecurityOptions_Disabled (1110.37s)
--- PASS: TestAccAWSElasticSearchDomain_AdvancedSecurityOptions_IAM (910.89s)
--- PASS: TestAccAWSElasticSearchDomain_AdvancedSecurityOptions_UserDB (2315.72s)
--- PASS: TestAccAWSElasticSearchDomain_basic (828.97s)
--- PASS: TestAccAWSElasticSearchDomain_ClusterConfig_ZoneAwarenessConfig (6476.66s)
--- PASS: TestAccAWSElasticSearchDomain_CognitoOptionsCreateAndRemove (1678.06s)
--- PASS: TestAccAWSElasticSearchDomain_CognitoOptionsUpdate (2566.28s)
--- PASS: TestAccAWSElasticSearchDomain_complex (1058.50s)
--- PASS: TestAccAWSElasticSearchDomain_CustomEndpoint (2500.69s)
--- PASS: TestAccAWSElasticSearchDomain_duplicate (712.87s)
--- PASS: TestAccAWSElasticSearchDomain_encrypt_at_rest_default_key (993.05s)
--- PASS: TestAccAWSElasticSearchDomain_encrypt_at_rest_specify_key (1464.85s)
--- PASS: TestAccAWSElasticSearchDomain_internetToVpcEndpoint (2329.21s)
--- PASS: TestAccAWSElasticSearchDomain_LogPublishingOptions_AuditLogs (1158.98s)
--- PASS: TestAccAWSElasticSearchDomain_LogPublishingOptions_EsApplicationLogs (1519.00s)
--- PASS: TestAccAWSElasticSearchDomain_LogPublishingOptions_IndexSlowLogs (858.37s)
--- PASS: TestAccAWSElasticSearchDomain_LogPublishingOptions_SearchSlowLogs (1081.40s)
--- PASS: TestAccAWSElasticSearchDomain_NodeToNodeEncryption (938.28s)
--- PASS: TestAccAWSElasticSearchDomain_policy (1332.27s)
--- PASS: TestAccAWSElasticSearchDomain_RequireHTTPS (1653.56s)
--- PASS: TestAccAWSElasticSearchDomain_tags (1714.35s)
--- PASS: TestAccAWSElasticSearchDomain_update (2329.18s)
--- PASS: TestAccAWSElasticSearchDomain_update_version (4438.77s)
--- PASS: TestAccAWSElasticSearchDomain_update_volume_type (3179.57s)
--- PASS: TestAccAWSElasticSearchDomain_v23 (1237.71s)
--- PASS: TestAccAWSElasticSearchDomain_vpc (930.36s)
--- PASS: TestAccAWSElasticSearchDomain_vpc_update (3231.96s)
--- PASS: TestAccAWSElasticSearchDomain_warm (6666.88s)
--- PASS: TestAccAWSElasticSearchDomain_withDedicatedMaster (3033.83s)
--- PASS: TestAccAWSElasticSearchDomain_WithVolumeType_Missing (840.98s)
```
  • Loading branch information
matiaszilli authored Mar 31, 2021
1 parent 47b0d8b commit 4b1eeff
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 4 deletions.
28 changes: 27 additions & 1 deletion aws/resource_aws_elasticsearch_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ func resourceAwsElasticSearchDomain() *schema.Resource {
Schema: map[string]*schema.Schema{
"enforce_https": {
Type: schema.TypeBool,
Required: true,
Optional: true,
Default: true,
},
"tls_security_policy": {
Type: schema.TypeString,
Expand All @@ -152,6 +153,22 @@ func resourceAwsElasticSearchDomain() *schema.Resource {
elasticsearch.TLSSecurityPolicyPolicyMinTls12201907,
}, false),
},
"custom_endpoint_enabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"custom_endpoint": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: isCustomEndpointDisabled,
},
"custom_endpoint_certificate_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
DiffSuppressFunc: isCustomEndpointDisabled,
},
},
},
},
Expand Down Expand Up @@ -1038,6 +1055,15 @@ func isDedicatedMasterDisabled(k, old, new string, d *schema.ResourceData) bool
return false
}

func isCustomEndpointDisabled(k, old, new string, d *schema.ResourceData) bool {
v, ok := d.GetOk("domain_endpoint_options")
if ok {
domainEndpointOptions := v.([]interface{})[0].(map[string]interface{})
return !domainEndpointOptions["custom_endpoint_enabled"].(bool)
}
return false
}

func expandESNodeToNodeEncryptionOptions(s map[string]interface{}) *elasticsearch.NodeToNodeEncryptionOptions {
options := elasticsearch.NodeToNodeEncryptionOptions{}

Expand Down
101 changes: 101 additions & 0 deletions aws/resource_aws_elasticsearch_domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,58 @@ func TestAccAWSElasticSearchDomain_RequireHTTPS(t *testing.T) {
})
}

func TestAccAWSElasticSearchDomain_CustomEndpoint(t *testing.T) {
var domain elasticsearch.ElasticsearchDomainStatus
ri := acctest.RandInt()
resourceId := fmt.Sprintf("tf-test-%d", ri)
resourceName := "aws_elasticsearch_domain.example"
customEndpoint := fmt.Sprintf("%s.example.com", resourceId)
certResourceName := "aws_acm_certificate.example"
certKey := tlsRsaPrivateKeyPem(2048)
certificate := tlsRsaX509SelfSignedCertificatePem(certKey, customEndpoint)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, elasticsearch.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckESDomainDestroy,
Steps: []resource.TestStep{
{
Config: testAccESDomainConfig_CustomEndpoint(ri, true, "Policy-Min-TLS-1-0-2019-07", true, customEndpoint, certKey, certificate),
Check: resource.ComposeTestCheckFunc(
testAccCheckESDomainExists(resourceName, &domain),
resource.TestCheckResourceAttr(resourceName, "domain_endpoint_options.#", "1"),
resource.TestCheckResourceAttr(resourceName, "domain_endpoint_options.0.custom_endpoint_enabled", "true"),
resource.TestCheckResourceAttrSet(resourceName, "domain_endpoint_options.0.custom_endpoint"),
resource.TestCheckResourceAttrPair(resourceName, "domain_endpoint_options.0.custom_endpoint_certificate_arn", certResourceName, "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateId: resourceId,
ImportStateVerify: true,
},
{
Config: testAccESDomainConfig_CustomEndpoint(ri, true, "Policy-Min-TLS-1-0-2019-07", true, customEndpoint, certKey, certificate),
Check: resource.ComposeTestCheckFunc(
testAccCheckESDomainExists(resourceName, &domain),
testAccCheckESDomainEndpointOptions(true, "Policy-Min-TLS-1-0-2019-07", &domain),
testAccCheckESCustomEndpoint(resourceName, true, customEndpoint, &domain),
),
},
{
Config: testAccESDomainConfig_CustomEndpoint(ri, true, "Policy-Min-TLS-1-0-2019-07", false, customEndpoint, certKey, certificate),
Check: resource.ComposeTestCheckFunc(
testAccCheckESDomainExists(resourceName, &domain),
testAccCheckESDomainEndpointOptions(true, "Policy-Min-TLS-1-0-2019-07", &domain),
testAccCheckESCustomEndpoint(resourceName, false, customEndpoint, &domain),
),
},
},
})
}

func TestAccAWSElasticSearchDomain_ClusterConfig_ZoneAwarenessConfig(t *testing.T) {
var domain1, domain2, domain3, domain4 elasticsearch.ElasticsearchDomainStatus
rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(16)) // len = 28
Expand Down Expand Up @@ -1165,6 +1217,29 @@ func testAccCheckESDomainEndpointOptions(enforceHTTPS bool, tls string, status *
}
}

func testAccCheckESCustomEndpoint(n string, customEndpointEnabled bool, customEndpoint string, status *elasticsearch.ElasticsearchDomainStatus) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
options := status.DomainEndpointOptions
if *options.CustomEndpointEnabled != customEndpointEnabled {
return fmt.Errorf("CustomEndpointEnabled differ. Given: %t, Expected: %t", *options.CustomEndpointEnabled, customEndpointEnabled)
}
if *options.CustomEndpointEnabled {
if *options.CustomEndpoint != customEndpoint {
return fmt.Errorf("CustomEndpoint differ. Given: %s, Expected: %s", *options.CustomEndpoint, customEndpoint)
}
customEndpointCertificateArn := rs.Primary.Attributes["domain_endpoint_options.0.custom_endpoint_certificate_arn"]
if *options.CustomEndpointCertificateArn != customEndpointCertificateArn {
return fmt.Errorf("CustomEndpointCertificateArn differ. Given: %s, Expected: %s", *options.CustomEndpointCertificateArn, customEndpointCertificateArn)
}
}
return nil
}
}

func testAccCheckESNumberOfSecurityGroups(numberOfSecurityGroups int, status *elasticsearch.ElasticsearchDomainStatus) resource.TestCheckFunc {
return func(s *terraform.State) error {
count := len(status.VPCOptions.SecurityGroupIds)
Expand Down Expand Up @@ -1429,6 +1504,32 @@ resource "aws_elasticsearch_domain" "example" {
`, randInt, enforceHttps, tlsSecurityPolicy)
}

func testAccESDomainConfig_CustomEndpoint(randInt int, enforceHttps bool, tlsSecurityPolicy string, customEndpointEnabled bool, customEndpoint string, certKey string, certBody string) string {
return fmt.Sprintf(`
resource "aws_acm_certificate" "example" {
private_key = "%[6]s"
certificate_body = "%[7]s"
}
resource "aws_elasticsearch_domain" "example" {
domain_name = "tf-test-%[1]d"
domain_endpoint_options {
enforce_https = %[2]t
tls_security_policy = %[3]q
custom_endpoint_enabled = %[4]t
custom_endpoint = "%[5]s"
custom_endpoint_certificate_arn = aws_acm_certificate.example.arn
}
ebs_options {
ebs_enabled = true
volume_size = 10
}
}
`, randInt, enforceHttps, tlsSecurityPolicy, customEndpointEnabled, customEndpoint, tlsPemEscapeNewlines(certKey), tlsPemEscapeNewlines(certBody))
}

func testAccESDomainConfig_ClusterConfig_ZoneAwarenessConfig_AvailabilityZoneCount(rName string, availabilityZoneCount int) string {
return fmt.Sprintf(`
resource "aws_elasticsearch_domain" "test" {
Expand Down
27 changes: 25 additions & 2 deletions aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,20 @@ func expandESDomainEndpointOptions(l []interface{}) *elasticsearch.DomainEndpoin
domainEndpointOptions.TLSSecurityPolicy = aws.String(v)
}

if customEndpointEnabled, ok := m["custom_endpoint_enabled"]; ok {
domainEndpointOptions.CustomEndpointEnabled = aws.Bool(customEndpointEnabled.(bool))

if customEndpointEnabled.(bool) {
if v, ok := m["custom_endpoint"].(string); ok && v != "" {
domainEndpointOptions.CustomEndpoint = aws.String(v)
}

if v, ok := m["custom_endpoint_certificate_arn"].(string); ok && v != "" {
domainEndpointOptions.CustomEndpointCertificateArn = aws.String(v)
}
}
}

return domainEndpointOptions
}

Expand All @@ -1367,8 +1381,17 @@ func flattenESDomainEndpointOptions(domainEndpointOptions *elasticsearch.DomainE
}

m := map[string]interface{}{
"enforce_https": aws.BoolValue(domainEndpointOptions.EnforceHTTPS),
"tls_security_policy": aws.StringValue(domainEndpointOptions.TLSSecurityPolicy),
"enforce_https": aws.BoolValue(domainEndpointOptions.EnforceHTTPS),
"tls_security_policy": aws.StringValue(domainEndpointOptions.TLSSecurityPolicy),
"custom_endpoint_enabled": aws.BoolValue(domainEndpointOptions.CustomEndpointEnabled),
}
if aws.BoolValue(domainEndpointOptions.CustomEndpointEnabled) {
if domainEndpointOptions.CustomEndpoint != nil {
m["custom_endpoint"] = aws.StringValue(domainEndpointOptions.CustomEndpoint)
}
if domainEndpointOptions.CustomEndpointCertificateArn != nil {
m["custom_endpoint_certificate_arn"] = aws.StringValue(domainEndpointOptions.CustomEndpointCertificateArn)
}
}

return []interface{}{m}
Expand Down
5 changes: 4 additions & 1 deletion website/docs/r/elasticsearch_domain.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,11 @@ The **advanced_security_options** block supports the following attributes:

**domain_endpoint_options** supports the following attributes:

* `enforce_https` - (Required) Whether or not to require HTTPS
* `enforce_https` - (Optional) Whether or not to require HTTPS. Defaults to `true`.
* `tls_security_policy` - (Optional) The name of the TLS security policy that needs to be applied to the HTTPS endpoint. Valid values: `Policy-Min-TLS-1-0-2019-07` and `Policy-Min-TLS-1-2-2019-07`. Terraform will only perform drift detection if a configuration value is provided.
* `custom_endpoint_enabled` - (Optional) Whether to enable custom endpoint for the Elasticsearch domain
* `custom_endpoint` - (Optional) Fully qualified domain for your custom endpoint
* `custom_endpoint_certificate_arn` - (Optional) ACM certificate ARN for your custom endpoint

**cluster_config** supports the following attributes:

Expand Down

0 comments on commit 4b1eeff

Please sign in to comment.