Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add attrs related to endpoint v2 for aws_opensearch_domain #38456

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading