Skip to content

Commit

Permalink
Merge pull request #38456 from acwwat/f-aws_opensearch_domain-add_end…
Browse files Browse the repository at this point in the history
…point_v2_attrs

feat: Add attrs related to endpoint v2 for aws_opensearch_domain
  • Loading branch information
ewbankkit authored Aug 21, 2024
2 parents e9713db + 6ae0eff commit e2afe00
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .changelog/38456.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_opensearch_domain: Add `dashboard_endpoint_v2`, `domain_endpoint_v2_hosted_zone_id`, and `endpoint_v2` attributes
```

```release-note:enhancement
data-source/aws_opensearch_domain: Add `dashboard_endpoint_v2`, `domain_endpoint_v2_hosted_zone_id`, and `endpoint_v2` attributes
```
40 changes: 32 additions & 8 deletions internal/service/opensearch/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ func resourceDomain() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"dashboard_endpoint_v2": {
Type: schema.TypeString,
Computed: true,
},
"domain_endpoint_options": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -391,6 +395,10 @@ func resourceDomain() *schema.Resource {
},
},
},
"domain_endpoint_v2_hosted_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"domain_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -463,6 +471,10 @@ func resourceDomain() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"endpoint_v2": {
Type: schema.TypeString,
Computed: true,
},
names.AttrEngineVersion: {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -863,6 +875,7 @@ func resourceDomainRead(ctx context.Context, d *schema.ResourceData, meta interf

d.SetId(aws.ToString(ds.ARN))
d.Set(names.AttrARN, ds.ARN)
d.Set("domain_endpoint_v2_hosted_zone_id", ds.DomainEndpointV2HostedZoneId)
d.Set("domain_id", ds.DomainId)
d.Set(names.AttrDomainName, ds.DomainName)
d.Set(names.AttrEngineVersion, ds.EngineVersion)
Expand Down Expand Up @@ -922,16 +935,27 @@ func resourceDomainRead(ctx context.Context, d *schema.ResourceData, meta interf

endpoints := flex.FlattenStringValueMap(ds.Endpoints)
d.Set(names.AttrEndpoint, endpoints["vpc"])
d.Set("dashboard_endpoint", getDashboardEndpoint(d))
d.Set("kibana_endpoint", getKibanaEndpoint(d))
d.Set("dashboard_endpoint", getDashboardEndpoint(d.Get(names.AttrEndpoint).(string)))
d.Set("kibana_endpoint", getKibanaEndpoint(d.Get(names.AttrEndpoint).(string)))
if endpoints["vpcv2"] != nil {
d.Set("endpoint_v2", endpoints["vpcv2"])
d.Set("dashboard_endpoint_v2", getDashboardEndpoint(d.Get("endpoint_v2").(string)))
}
if ds.Endpoint != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch Domain in VPC expected to have null Endpoint value", d.Id())
}
if ds.EndpointV2 != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch Domain in VPC expected to have null EndpointV2 value", d.Id())
}
} else {
if ds.Endpoint != nil {
d.Set(names.AttrEndpoint, ds.Endpoint)
d.Set("dashboard_endpoint", getDashboardEndpoint(d))
d.Set("kibana_endpoint", getKibanaEndpoint(d))
d.Set("dashboard_endpoint", getDashboardEndpoint(d.Get(names.AttrEndpoint).(string)))
d.Set("kibana_endpoint", getKibanaEndpoint(d.Get(names.AttrEndpoint).(string)))
}
if ds.EndpointV2 != nil {
d.Set("endpoint_v2", ds.EndpointV2)
d.Set("dashboard_endpoint_v2", getDashboardEndpoint(d.Get("endpoint_v2").(string)))
}
if ds.Endpoints != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch Domain not in VPC expected to have null Endpoints value", d.Id())
Expand Down Expand Up @@ -1197,12 +1221,12 @@ func suppressEquivalentKMSKeyIDs(k, old, new string, d *schema.ResourceData) boo
return strings.Contains(old, new)
}

func getDashboardEndpoint(d *schema.ResourceData) string {
return d.Get(names.AttrEndpoint).(string) + "/_dashboards"
func getDashboardEndpoint(endpoint string) string {
return endpoint + "/_dashboards"
}

func getKibanaEndpoint(d *schema.ResourceData) string {
return d.Get(names.AttrEndpoint).(string) + "/_plugin/kibana/"
func getKibanaEndpoint(endpoint string) string {
return endpoint + "/_plugin/kibana/"
}

func suppressComputedDedicatedMaster(k, old, new string, d *schema.ResourceData) bool {
Expand Down
36 changes: 30 additions & 6 deletions internal/service/opensearch/domain_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,18 @@ func dataSourceDomain() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"dashboard_endpoint_v2": {
Type: schema.TypeString,
Computed: true,
},
"deleted": {
Type: schema.TypeBool,
Computed: true,
},
"domain_endpoint_v2_hosted_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"domain_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -273,6 +281,10 @@ func dataSourceDomain() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"endpoint_v2": {
Type: schema.TypeString,
Computed: true,
},
names.AttrEngineVersion: {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -455,10 +467,11 @@ func dataSourceDomainRead(ctx context.Context, d *schema.ResourceData, meta inte
}

d.Set(names.AttrARN, ds.ARN)
d.Set("domain_endpoint_v2_hosted_zone_id", ds.DomainEndpointV2HostedZoneId)
d.Set("domain_id", ds.DomainId)
d.Set(names.AttrEndpoint, ds.Endpoint)
d.Set("dashboard_endpoint", getDashboardEndpoint(d))
d.Set("kibana_endpoint", getKibanaEndpoint(d))
d.Set("dashboard_endpoint", getDashboardEndpoint(d.Get(names.AttrEndpoint).(string)))
d.Set("kibana_endpoint", getKibanaEndpoint(d.Get(names.AttrEndpoint).(string)))

if err := d.Set("advanced_security_options", flattenAdvancedSecurityOptions(ds.AdvancedSecurityOptions)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting advanced_security_options: %s", err)
Expand Down Expand Up @@ -503,16 +516,27 @@ func dataSourceDomainRead(ctx context.Context, d *schema.ResourceData, meta inte
if err := d.Set(names.AttrEndpoint, endpoints["vpc"]); err != nil {
return sdkdiag.AppendErrorf(diags, "setting endpoint: %s", err)
}
d.Set("dashboard_endpoint", getDashboardEndpoint(d))
d.Set("kibana_endpoint", getKibanaEndpoint(d))
d.Set("dashboard_endpoint", getDashboardEndpoint(d.Get(names.AttrEndpoint).(string)))
d.Set("kibana_endpoint", getKibanaEndpoint(d.Get(names.AttrEndpoint).(string)))
if endpoints["vpcv2"] != nil {
d.Set("endpoint_v2", endpoints["vpcv2"])
d.Set("dashboard_endpoint_v2", getDashboardEndpoint(d.Get("endpoint_v2").(string)))
}
if ds.Endpoint != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch domain in VPC expected to have null Endpoint value", d.Id())
}
if ds.EndpointV2 != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch Domain in VPC expected to have null EndpointV2 value", d.Id())
}
} else {
if ds.Endpoint != nil {
d.Set(names.AttrEndpoint, ds.Endpoint)
d.Set("dashboard_endpoint", getDashboardEndpoint(d))
d.Set("kibana_endpoint", getKibanaEndpoint(d))
d.Set("dashboard_endpoint", getDashboardEndpoint(d.Get(names.AttrEndpoint).(string)))
d.Set("kibana_endpoint", getKibanaEndpoint(d.Get(names.AttrEndpoint).(string)))
}
if ds.EndpointV2 != nil {
d.Set("endpoint_v2", ds.EndpointV2)
d.Set("dashboard_endpoint_v2", getDashboardEndpoint(d.Get("endpoint_v2").(string)))
}
if ds.Endpoints != nil {
return sdkdiag.AppendErrorf(diags, "%q: OpenSearch domain not in VPC expected to have null Endpoints value", d.Id())
Expand Down
118 changes: 114 additions & 4 deletions internal/service/opensearch/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,50 @@ func TestAccOpenSearchDomain_VPC_internetToVPCEndpoint(t *testing.T) {
})
}

func TestAccOpenSearchDomain_VPC_ipAddressType(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
t.Skip("skipping long-running test in short mode")
}

var domain awstypes.DomainStatus
rName := testAccRandomDomainName()
resourceName := "aws_opensearch_domain.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckIAMServiceLinkedRole(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.OpenSearchServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckDomainDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccDomainConfig_vpcIPAddressType(rName, "dualstack"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestMatchResourceAttr(resourceName, "dashboard_endpoint_v2", regexache.MustCompile(`.+?\.on\.aws\/_dashboards`)),
resource.TestMatchResourceAttr(resourceName, "endpoint_v2", regexache.MustCompile(`.+?\.on\.aws`)),
resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, "dualstack"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateId: rName,
ImportStateVerify: true,
},
{
Config: testAccDomainConfig_vpcIPAddressType(rName, "ipv4"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestCheckNoResourceAttr(resourceName, "dashboard_endpoint_v2"),
resource.TestCheckNoResourceAttr(resourceName, "endpoint_v2"),
resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, "ipv4"),
),
},
},
})
}

func TestAccOpenSearchDomain_ipAddressType(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
Expand All @@ -784,8 +828,8 @@ func TestAccOpenSearchDomain_ipAddressType(t *testing.T) {
Config: testAccDomainConfig_ipAddressType(rName, "dualstack"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestMatchResourceAttr(resourceName, "dashboard_endpoint", regexache.MustCompile(`.*(opensearch|es)\..*/_dashboards`)),
resource.TestCheckResourceAttrSet(resourceName, names.AttrEngineVersion),
resource.TestMatchResourceAttr(resourceName, "dashboard_endpoint_v2", regexache.MustCompile(`.+?\.on\.aws\/_dashboards`)),
resource.TestMatchResourceAttr(resourceName, "endpoint_v2", regexache.MustCompile(`.+?\.on\.aws`)),
resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, "dualstack"),
),
},
Expand All @@ -799,8 +843,8 @@ func TestAccOpenSearchDomain_ipAddressType(t *testing.T) {
Config: testAccDomainConfig_ipAddressType(rName, "ipv4"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDomainExists(ctx, resourceName, &domain),
resource.TestMatchResourceAttr(resourceName, "dashboard_endpoint", regexache.MustCompile(`.*(opensearch|es)\..*/_dashboards`)),
resource.TestCheckResourceAttrSet(resourceName, names.AttrEngineVersion),
resource.TestCheckNoResourceAttr(resourceName, "dashboard_endpoint_v2"),
resource.TestCheckNoResourceAttr(resourceName, "endpoint_v2"),
resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, "ipv4"),
),
},
Expand Down Expand Up @@ -3138,6 +3182,72 @@ resource "aws_opensearch_domain" "test" {
`, rName))
}

func testAccDomainConfig_vpcIPAddressType(rName, ipAddressType string) string {
return acctest.ConfigCompose(
acctest.ConfigAvailableAZsNoOptIn(),
fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "192.168.0.0/22"
assign_generated_ipv6_cidr_block = true
tags = {
Name = %[1]q
}
}
resource "aws_subnet" "test" {
vpc_id = aws_vpc.test.id
availability_zone = data.aws_availability_zones.available.names[0]
cidr_block = "192.168.0.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 4, 0)
tags = {
Name = %[1]q
}
}
resource "aws_subnet" "test2" {
vpc_id = aws_vpc.test.id
availability_zone = data.aws_availability_zones.available.names[1]
cidr_block = "192.168.1.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 4, 1)
tags = {
Name = %[1]q
}
}
resource "aws_security_group" "test" {
vpc_id = aws_vpc.test.id
}
resource "aws_security_group" "test2" {
vpc_id = aws_vpc.test.id
}
resource "aws_opensearch_domain" "test" {
domain_name = %[1]q
ip_address_type = %[2]q
ebs_options {
ebs_enabled = true
volume_size = 10
}
cluster_config {
instance_count = 2
zone_awareness_enabled = true
instance_type = "t2.small.search"
}
vpc_options {
security_group_ids = [aws_security_group.test.id, aws_security_group.test2.id]
subnet_ids = [aws_subnet.test.id, aws_subnet.test2.id]
}
}
`, rName, ipAddressType))
}

func testAccDomainConfig_vpcUpdate1(rName string) string {
return acctest.ConfigCompose(
acctest.ConfigAvailableAZsNoOptIn(),
Expand Down
3 changes: 3 additions & 0 deletions website/docs/d/opensearch_domain.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ This data source exports the following attributes in addition to the arguments a
* `role_arn` - IAM Role with the AmazonOpenSearchServiceCognitoAccess policy attached.
* `created` – Status of the creation of the domain.
* `dashboard_endpoint` - Domain-specific endpoint used to access the [Dashboard application](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/dashboards.html).
* `dashboard_endpoint_v2` - V2 domain-specific endpoint used to access the [Dashboard application](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/dashboards.html)
* `deleted` – Status of the deletion of the domain.
* `domain_endpoint_v2_hosted_zone_id` - Dual stack hosted zone ID for the domain.
* `domain_id` – Unique identifier for the domain.
* `ebs_options` - EBS Options for the instances in the domain.
* `ebs_enabled` - Whether EBS volumes are attached to data nodes in the domain.
Expand All @@ -79,6 +81,7 @@ This data source exports the following attributes in addition to the arguments a
* `enabled` - Whether encryption at rest is enabled in the domain.
* `kms_key_id` - KMS key id used to encrypt data at rest.
* `endpoint` – Domain-specific endpoint used to submit index, search, and data upload requests.
* `endpoint_v2` - V2 domain-specific endpoint that works with both IPv4 and IPv6 addresses, used to submit index, search, and data upload requests.
* `ip_address_type` - Type of IP addresses supported by the endpoint for the domain.
* `kibana_endpoint` - (**Deprecated**) Domain-specific endpoint for kibana without https scheme. Use the `dashboard_endpoint` attribute instead.
* `log_publishing_options` - Domain log publishing related options.
Expand Down
3 changes: 3 additions & 0 deletions website/docs/r/opensearch_domain.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,13 @@ AWS documentation: [Off Peak Hours Support for Amazon OpenSearch Service Domains
This resource exports the following attributes in addition to the arguments above:

* `arn` - ARN of the domain.
* `domain_endpoint_v2_hosted_zone_id` - Dual stack hosted zone ID for the domain.
* `domain_id` - Unique identifier for the domain.
* `domain_name` - Name of the OpenSearch domain.
* `endpoint` - Domain-specific endpoint used to submit index, search, and data upload requests.
* `endpoint_v2` - V2 domain endpoint that works with both IPv4 and IPv6 addresses, used to submit index, search, and data upload requests.
* `dashboard_endpoint` - Domain-specific endpoint for Dashboard without https scheme.
* `dashboard_endpoint_v2` - V2 domain endpoint for Dashboard that works with both IPv4 and IPv6 addresses, without https scheme.
* `kibana_endpoint` - (**Deprecated**) Domain-specific endpoint for kibana without https scheme. Use the `dashboard_endpoint` attribute instead.
* `tags_all` - Map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block).
* `vpc_options.0.availability_zones` - If the domain was created inside a VPC, the names of the availability zones the configured `subnet_ids` were created inside.
Expand Down

0 comments on commit e2afe00

Please sign in to comment.