Repository: kubernetes-sigs/external-dns (language: go)

Issue:
AWSSD: Remove GetServiceDetail
<!-- Please only use this template for submitting enhancement requests. This can be something like a new provider or a new gateway.  -->

**What would you like to be added**:
AWSSD provider should stop using AWS `GetService` API call to get info about Services.

**Why is this needed**:
`GetService` [API](https://docs.aws.amazon.com/cloud-map/latest/api/API_GetService.html) usage is excessive and can be omitted as Service data is already returned by `ListServices` [API](https://docs.aws.amazon.com/cloud-map/latest/api/API_ListServices.html).
`GetService` got a default quota of 50 tps; *tps - tokens per second*
When external-dns is used with CloudMap Namespace which contains several thousand of Services - `GetService` API calls will take nultiple minutes to complete.


Discussion / hints:

Fix patch:
diff --git a/provider/awssd/aws_sd.go b/provider/awssd/aws_sd.go
index d3d3390b1f..1bf9f3251d 100644
--- a/provider/awssd/aws_sd.go
+++ b/provider/awssd/aws_sd.go
@@ -64,7 +64,6 @@ var (
 type AWSSDClient interface {
 	CreateService(input *sd.CreateServiceInput) (*sd.CreateServiceOutput, error)
 	DeregisterInstance(input *sd.DeregisterInstanceInput) (*sd.DeregisterInstanceOutput, error)
-	GetService(input *sd.GetServiceInput) (*sd.GetServiceOutput, error)
 	ListInstancesPages(input *sd.ListInstancesInput, fn func(*sd.ListInstancesOutput, bool) bool) error
 	ListNamespacesPages(input *sd.ListNamespacesInput, fn func(*sd.ListNamespacesOutput, bool) bool) error
 	ListServicesPages(input *sd.ListServicesInput, fn func(*sd.ListServicesOutput, bool) bool) error
@@ -359,13 +358,10 @@ func (p *AWSSDProvider) ListNamespaces() ([]*sd.NamespaceSummary, error) {
 
 // ListServicesByNamespaceID returns list of services in given namespace. Returns map[srv_name]*sd.Service
 func (p *AWSSDProvider) ListServicesByNamespaceID(namespaceID *string) (map[string]*sd.Service, error) {
-	serviceIds := make([]*string, 0)
+	services := make([]*sd.ServiceSummary, 0)
 
 	f := func(resp *sd.ListServicesOutput, lastPage bool) bool {
-		for _, srv := range resp.Services {
-			serviceIds = append(serviceIds, srv.Id)
-		}
-
+		services = append(services, resp.Services...)
 		return true
 	}
 
@@ -374,35 +370,31 @@ func (p *AWSSDProvider) ListServicesByNamespaceID(namespaceID *string) (map[stri
 			Name:   aws.String(sd.ServiceFilterNameNamespaceId),
 			Values: []*string{namespaceID},
 		}},
+		MaxResults: aws.Int64(100),
 	}, f)
 	if err != nil {
 		return nil, err
 	}
 
-	// get detail of each listed service
-	services := make(map[string]*sd.Service)
-	for _, serviceID := range serviceIds {
-		service, err := p.GetServiceDetail(serviceID)
-		if err != nil {
-			return nil, err
+	servicesMap := make(map[string]*sd.Service)
+	for _, serviceSummary := range services {
+		service := &sd.Service{
+			Arn:                     serviceSummary.Arn,
+			CreateDate:              serviceSummary.CreateDate,
+			Description:             serviceSummary.Description,
+			DnsConfig:               serviceSummary.DnsConfig,
+			HealthCheckConfig:       serviceSummary.HealthCheckConfig,
+			HealthCheckCustomConfig: serviceSummary.HealthCheckCustomConfig,
+			Id:                      serviceSummary.Id,
+			InstanceCount:           serviceSummary.InstanceCount,
+			Name:                    serviceSummary.Name,
+			NamespaceId:             namespaceID,
+			Type:                    serviceSummary.Type,
 		}
 
-		services[aws.StringValue(service.Name)] = service
-	}
-
-	return services, nil
-}
-
-// GetServiceDetail returns detail of given service
-func (p *AWSSDProvider) GetServiceDetail(serviceID *string) (*sd.Service, error) {
-	output, err := p.client.GetService(&sd.GetServiceInput{
-		Id: serviceID,
-	})
-	if err != nil {
-		return nil, err
+		servicesMap[aws.StringValue(service.Name)] = service
 	}
-
-	return output.Service, nil
+	return servicesMap, nil
 }
 
 // ListInstancesByServiceID returns list of instances registered in given service.
@@ -578,11 +570,16 @@ func serviceToServiceSummary(service *sd.Service) *sd.ServiceSummary {
 	}
 
 	return &sd.ServiceSummary{
-		Name:          service.Name,
-		Id:            service.Id,
-		Arn:           service.Arn,
-		Description:   service.Description,
-		InstanceCount: service.InstanceCount,
+		Arn:                     service.Arn,
+		CreateDate:              service.CreateDate,
+		Description:             service.Description,
+		DnsConfig:               service.DnsConfig,
+		HealthCheckConfig:       service.HealthCheckConfig,
+		HealthCheckCustomConfig: service.HealthCheckCustomConfig,
+		Id:                      service.Id,
+		InstanceCount:           service.InstanceCount,
+		Name:                    service.Name,
+		Type:                    service.Type,
 	}
 }
 


Test patch:
diff --git a/provider/awssd/aws_sd_test.go b/provider/awssd/aws_sd_test.go
index 0ac5db5560..3a2a8b9eb0 100644
--- a/provider/awssd/aws_sd_test.go
+++ b/provider/awssd/aws_sd_test.go
@@ -413,18 +413,21 @@ func TestAWSSDProvider_ListServicesByNamespace(t *testing.T) {
 	services := map[string]map[string]*sd.Service{
 		"private": {
 			"srv1": {
-				Id:   aws.String("srv1"),
-				Name: aws.String("service1"),
+				Id:          aws.String("srv1"),
+				Name:        aws.String("service1"),
+				NamespaceId: aws.String("private"),
 			},
 			"srv2": {
-				Id:   aws.String("srv2"),
-				Name: aws.String("service2"),
+				Id:          aws.String("srv2"),
+				Name:        aws.String("service2"),
+				NamespaceId: aws.String("private"),
 			},
 		},
 		"public": {
 			"srv3": {
-				Id:   aws.String("srv3"),
-				Name: aws.String("service3"),
+				Id:          aws.String("srv3"),
+				Name:        aws.String("service3"),
+				NamespaceId: aws.String("public"),
 			},
 		},
 	}
@@ -443,10 +446,7 @@ func TestAWSSDProvider_ListServicesByNamespace(t *testing.T) {
 
 		result, err := provider.ListServicesByNamespaceID(namespaces["private"].Id)
 		require.NoError(t, err)
-
-		if !reflect.DeepEqual(result, tc.expectedServices) {
-			t.Errorf("AWSSDProvider.ListServicesByNamespaceID() error = %v, wantErr %v", result, tc.expectedServices)
-		}
+		assert.Equal(t, tc.expectedServices, result)
 	}
 }