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

New Data Sources: aws_service_discovery_service and aws_service_discovery_http_namespace #25162

Merged
merged 19 commits into from Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9b3cb8b
New Data Source: aws_service_discovery_service
brittandeyoung Jun 3, 2022
aca442a
New Data Source: aws_service_discovery_http_namespace
brittandeyoung Jun 3, 2022
eee52d7
Docs Lint fix and add changelog
brittandeyoung Jun 3, 2022
f2fb007
split change log new-data-source into two separate notes
brittandeyoung Jun 3, 2022
693b0d0
remove change log as it broke ci checks
brittandeyoung Jun 3, 2022
0d2d61a
add change log back
brittandeyoung Jun 3, 2022
ff00d5a
Tweak CHANGELOG entry.
ewbankkit Jun 24, 2022
69614af
r/aws_service_discovery_http_namespace: Add 'FindNamespaceByID'.
ewbankkit Jun 24, 2022
44ca1af
d/aws_service_discovery_http_namespace: Add 'findNamespaceByNameAndTy…
ewbankkit Jun 24, 2022
bf292d7
Handle nil Namespace.Properties.
ewbankkit Jun 24, 2022
b90b4bc
r/aws_service_discovery_private_dns_namespace: Use 'FindNamespaceByID'.
ewbankkit Jun 24, 2022
5f387d6
r/aws_service_discovery_public_dns_namespace: Use 'FindNamespaceByID'.
ewbankkit Jun 24, 2022
bc48924
d/aws_service_discovery_dns_namespace: Add 'tags' attribute.
ewbankkit Jun 24, 2022
60fec4d
r/aws_service_discovery_instance: Tidy up.
ewbankkit Jun 24, 2022
88b059c
r/aws_service_discovery_service: Tidy up.
ewbankkit Jun 24, 2022
d3c4acd
d/aws_service_discovery_service: Tidy up.
ewbankkit Jun 24, 2022
ae0daca
Switch to Plugin SDK v2 'WithoutTimeout' CRUD handler signatures.
ewbankkit Jun 24, 2022
109b5aa
Fix 'MD047/single-trailing-newline Files should end with a single new…
ewbankkit Jun 24, 2022
1b4415e
Tidy up ServiceDiscovery service sweepers.
ewbankkit Jun 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changelog/25162.txt
@@ -0,0 +1,15 @@
```release-note:new-data-source
aws_service_discovery_service
```

```release-note:new-data-source
aws_service_discovery_http_namespace
```

```release-note:enhancement
resource/aws_service_discovery_http_namespace: Add `http_name` attribute
```

```release-note:enhancement
data-source/aws_service_discovery_dns_namespace: Add `tags` attribute
```
4 changes: 3 additions & 1 deletion internal/provider/provider.go
Expand Up @@ -845,7 +845,9 @@ func Provider() *schema.Provider {
"aws_servicecatalog_portfolio": servicecatalog.DataSourcePortfolio(),
"aws_servicecatalog_product": servicecatalog.DataSourceProduct(),

"aws_service_discovery_dns_namespace": servicediscovery.DataSourceDNSNamespace(),
"aws_service_discovery_dns_namespace": servicediscovery.DataSourceDNSNamespace(),
"aws_service_discovery_http_namespace": servicediscovery.DataSourceHTTPNamespace(),
"aws_service_discovery_service": servicediscovery.DataSourceService(),

"aws_servicequotas_service": servicequotas.DataSourceService(),
"aws_servicequotas_service_quota": servicequotas.DataSourceServiceQuota(),
Expand Down
80 changes: 24 additions & 56 deletions internal/service/servicediscovery/dns_namespace_data_source.go
Expand Up @@ -2,14 +2,14 @@ package servicediscovery

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/servicediscovery"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
)

func DataSourceDNSNamespace() *schema.Resource {
Expand All @@ -33,9 +33,11 @@ func DataSourceDNSNamespace() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"tags": tftags.TagsSchemaComputed(),
"type": {
Type: schema.TypeString,
Required: true,
// HTTP namespaces are handled via the aws_service_discovery_http_namespace data source.
ValidateFunc: validation.StringInSlice([]string{
servicediscovery.NamespaceTypeDnsPublic,
servicediscovery.NamespaceTypeDnsPrivate,
Expand All @@ -47,77 +49,43 @@ func DataSourceDNSNamespace() *schema.Resource {

func dataSourceDNSNamespaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).ServiceDiscoveryConn
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

name := d.Get("name").(string)
nsType := d.Get("type").(string)
nsSummary, err := findNamespaceByNameAndType(ctx, conn, name, nsType)

input := &servicediscovery.ListNamespacesInput{}

var filters []*servicediscovery.NamespaceFilter

filter := &servicediscovery.NamespaceFilter{
Condition: aws.String(servicediscovery.FilterConditionEq),
Name: aws.String(servicediscovery.NamespaceFilterNameType),
Values: []*string{aws.String(d.Get("type").(string))},
if err != nil {
return diag.Errorf("reading Service Discovery %s Namespace (%s): %s", name, nsType, err)
}

filters = append(filters, filter)

input.Filters = filters
namespaceID := aws.StringValue(nsSummary.Id)

namespaceIds := make([]string, 0)

err := conn.ListNamespacesPagesWithContext(ctx, input, func(page *servicediscovery.ListNamespacesOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, namespace := range page.Namespaces {
if namespace == nil {
continue
}

if name == aws.StringValue(namespace.Name) {
namespaceIds = append(namespaceIds, aws.StringValue(namespace.Id))
}
}
return !lastPage
})
ns, err := FindNamespaceByID(ctx, conn, namespaceID)

if err != nil {
return diag.FromErr(fmt.Errorf("error listing Service Discovery DNS Namespaces: %w", err))
return diag.Errorf("reading Service Discovery %s Namespace (%s): %s", nsType, namespaceID, err)
}

if len(namespaceIds) == 0 {
return diag.Errorf("no matching Service Discovery DNS Namespace found")
d.SetId(namespaceID)
arn := aws.StringValue(ns.Arn)
d.Set("arn", arn)
d.Set("description", ns.Description)
if ns.Properties != nil && ns.Properties.DnsProperties != nil {
d.Set("hosted_zone", ns.Properties.DnsProperties.HostedZoneId)
} else {
d.Set("hosted_zone", nil)
}
d.Set("name", ns.Name)

if len(namespaceIds) != 1 {
return diag.FromErr(fmt.Errorf("search returned %d Service Discovery DNS Namespaces, please revise so only one is returned", len(namespaceIds)))
}

d.SetId(namespaceIds[0])

req := &servicediscovery.GetNamespaceInput{
Id: aws.String(d.Id()),
}

output, err := conn.GetNamespaceWithContext(ctx, req)
tags, err := ListTags(conn, arn)

if err != nil {
return diag.FromErr(fmt.Errorf("error reading Service Discovery DNS Namespace (%s): %w", d.Id(), err))
return diag.Errorf("listing tags for Service Discovery %s Namespace (%s): %s", nsType, arn, err)
}

if output == nil || output.Namespace == nil {
return diag.FromErr(fmt.Errorf("error reading Service Discovery DNS Namespace (%s): empty output", d.Id()))
}

namespace := output.Namespace

d.Set("name", namespace.Name)
d.Set("description", namespace.Description)
d.Set("arn", namespace.Arn)
if namespace.Properties != nil && namespace.Properties.DnsProperties != nil {
d.Set("hosted_zone", namespace.Properties.DnsProperties.HostedZoneId)
if err := d.Set("tags", tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return diag.Errorf("setting tags: %s", err)
}

return nil
Expand Down
Expand Up @@ -28,9 +28,10 @@ func TestAccServiceDiscoveryDNSNamespaceDataSource_private(t *testing.T) {
Config: testAccDNSNamespaceDataSourceConfig_private(rName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "hosted_zone", resourceName, "hosted_zone"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
),
},
},
Expand All @@ -55,9 +56,10 @@ func TestAccServiceDiscoveryDNSNamespaceDataSource_public(t *testing.T) {
Config: testAccDNSNamespaceDataSourceConfig_public(rName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "hosted_zone", resourceName, "hosted_zone"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
),
},
},
Expand All @@ -68,10 +70,14 @@ func testAccDNSNamespaceDataSourceConfig_private(rName string) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"

tags = {
Name = %[1]q
}
}

resource "aws_service_discovery_private_dns_namespace" "test" {
name = "%[1]s.tf"
name = "%[1]s.test"
vpc = aws_vpc.test.id
}

Expand All @@ -85,7 +91,7 @@ data "aws_service_discovery_dns_namespace" "test" {
func testAccDNSNamespaceDataSourceConfig_public(rName string) string {
return fmt.Sprintf(`
resource "aws_service_discovery_public_dns_namespace" "test" {
name = "%[1]s.tf"
name = "%[1]s.test"
}

data "aws_service_discovery_dns_namespace" "test" {
Expand Down
143 changes: 137 additions & 6 deletions internal/service/servicediscovery/find.go
@@ -1,20 +1,22 @@
package servicediscovery

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/servicediscovery"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func FindInstanceByServiceIDAndInstanceID(conn *servicediscovery.ServiceDiscovery, serviceID, instanceID string) (*servicediscovery.Instance, error) {
func FindInstanceByServiceIDAndInstanceID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, serviceID, instanceID string) (*servicediscovery.Instance, error) {
input := &servicediscovery.GetInstanceInput{
InstanceId: aws.String(instanceID),
ServiceId: aws.String(serviceID),
}

output, err := conn.GetInstance(input)
output, err := conn.GetInstanceWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, servicediscovery.ErrCodeInstanceNotFound) {
return nil, &resource.NotFoundError{
Expand All @@ -34,12 +36,89 @@ func FindInstanceByServiceIDAndInstanceID(conn *servicediscovery.ServiceDiscover
return output.Instance, nil
}

func FindOperationByID(conn *servicediscovery.ServiceDiscovery, id string) (*servicediscovery.Operation, error) {
func findNamespaces(ctx context.Context, conn *servicediscovery.ServiceDiscovery, input *servicediscovery.ListNamespacesInput) ([]*servicediscovery.NamespaceSummary, error) {
var output []*servicediscovery.NamespaceSummary

err := conn.ListNamespacesPagesWithContext(ctx, input, func(page *servicediscovery.ListNamespacesOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.Namespaces {
if v != nil {
output = append(output, v)
}
}

return !lastPage
})

if err != nil {
return nil, err
}

return output, nil
}

func findNamespacesByType(ctx context.Context, conn *servicediscovery.ServiceDiscovery, nsType string) ([]*servicediscovery.NamespaceSummary, error) {
input := &servicediscovery.ListNamespacesInput{
Filters: []*servicediscovery.NamespaceFilter{{
Condition: aws.String(servicediscovery.FilterConditionEq),
Name: aws.String(servicediscovery.NamespaceFilterNameType),
Values: aws.StringSlice([]string{nsType}),
}},
}

return findNamespaces(ctx, conn, input)
}

func findNamespaceByNameAndType(ctx context.Context, conn *servicediscovery.ServiceDiscovery, name, nsType string) (*servicediscovery.NamespaceSummary, error) {
output, err := findNamespacesByType(ctx, conn, nsType)

if err != nil {
return nil, err
}

for _, v := range output {
if aws.StringValue(v.Name) == name {
return v, nil
}
}

return nil, &resource.NotFoundError{}
}

func FindNamespaceByID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, id string) (*servicediscovery.Namespace, error) {
input := &servicediscovery.GetNamespaceInput{
Id: aws.String(id),
}

output, err := conn.GetNamespaceWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, servicediscovery.ErrCodeNamespaceNotFound) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.Namespace == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.Namespace, nil
}

func FindOperationByID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, id string) (*servicediscovery.Operation, error) {
input := &servicediscovery.GetOperationInput{
OperationId: aws.String(id),
}

output, err := conn.GetOperation(input)
output, err := conn.GetOperationWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, servicediscovery.ErrCodeOperationNotFound) {
return nil, &resource.NotFoundError{
Expand All @@ -59,12 +138,64 @@ func FindOperationByID(conn *servicediscovery.ServiceDiscovery, id string) (*ser
return output.Operation, nil
}

func FindServiceByID(conn *servicediscovery.ServiceDiscovery, id string) (*servicediscovery.Service, error) {
func findServices(ctx context.Context, conn *servicediscovery.ServiceDiscovery, input *servicediscovery.ListServicesInput) ([]*servicediscovery.ServiceSummary, error) {
var output []*servicediscovery.ServiceSummary

err := conn.ListServicesPagesWithContext(ctx, input, func(page *servicediscovery.ListServicesOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.Services {
if v != nil {
output = append(output, v)
}
}

return !lastPage
})

if err != nil {
return nil, err
}

return output, nil
}

func findServicesByNamespaceID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, namespaceID string) ([]*servicediscovery.ServiceSummary, error) {
input := &servicediscovery.ListServicesInput{
Filters: []*servicediscovery.ServiceFilter{{
Condition: aws.String(servicediscovery.FilterConditionEq),
Name: aws.String(servicediscovery.ServiceFilterNameNamespaceId),
Values: aws.StringSlice([]string{namespaceID}),
}},
}

return findServices(ctx, conn, input)
}

func findServiceByNameAndNamespaceID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, name, namespaceID string) (*servicediscovery.ServiceSummary, error) {
output, err := findServicesByNamespaceID(ctx, conn, namespaceID)

if err != nil {
return nil, err
}

for _, v := range output {
if aws.StringValue(v.Name) == name {
return v, nil
}
}

return nil, &resource.NotFoundError{}
}

func FindServiceByID(ctx context.Context, conn *servicediscovery.ServiceDiscovery, id string) (*servicediscovery.Service, error) {
input := &servicediscovery.GetServiceInput{
Id: aws.String(id),
}

output, err := conn.GetService(input)
output, err := conn.GetServiceWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, servicediscovery.ErrCodeServiceNotFound) {
return nil, &resource.NotFoundError{
Expand Down