fix(provider/aws-sd): fix namespace type filtering (#5682)

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
This commit is contained in:
Ivan Ka 2025-07-25 11:18:28 +01:00 committed by GitHub
parent 20ab886cb6
commit d8f31eb27e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 26 additions and 18 deletions

View File

@ -66,7 +66,7 @@
| `--google-zone-visibility=` | When using the Google provider, filter for zones with this visibility (optional, options: public, private) |
| `--alibaba-cloud-config-file="/etc/kubernetes/alibaba-cloud.json"` | When using the Alibaba Cloud provider, specify the Alibaba Cloud configuration file (required when --provider=alibabacloud) |
| `--alibaba-cloud-zone-type=` | When using the Alibaba Cloud provider, filter for zones of this type (optional, options: public, private) |
| `--aws-zone-type=` | When using the AWS provider, filter for zones of this type (optional, options: public, private) |
| `--aws-zone-type=` | When using the AWS provider, filter for zones of this type (optional, default: any, options: public, private) |
| `--aws-zone-tags=` | When using the AWS provider, filter for zones with these tags |
| `--aws-profile=` | When using the AWS provider, name of the profile to use |
| `--aws-assume-role=""` | When using the AWS API, assume this IAM role. Useful for hosted zones in another AWS account. Specify the full ARN, e.g. `arn:aws:iam::123455567:role/external-dns` (optional) |

View File

@ -504,7 +504,7 @@ func App(cfg *Config) *kingpin.Application {
app.Flag("google-zone-visibility", "When using the Google provider, filter for zones with this visibility (optional, options: public, private)").Default(defaultConfig.GoogleZoneVisibility).EnumVar(&cfg.GoogleZoneVisibility, "", "public", "private")
app.Flag("alibaba-cloud-config-file", "When using the Alibaba Cloud provider, specify the Alibaba Cloud configuration file (required when --provider=alibabacloud)").Default(defaultConfig.AlibabaCloudConfigFile).StringVar(&cfg.AlibabaCloudConfigFile)
app.Flag("alibaba-cloud-zone-type", "When using the Alibaba Cloud provider, filter for zones of this type (optional, options: public, private)").Default(defaultConfig.AlibabaCloudZoneType).EnumVar(&cfg.AlibabaCloudZoneType, "", "public", "private")
app.Flag("aws-zone-type", "When using the AWS provider, filter for zones of this type (optional, options: public, private)").Default(defaultConfig.AWSZoneType).EnumVar(&cfg.AWSZoneType, "", "public", "private")
app.Flag("aws-zone-type", "When using the AWS provider, filter for zones of this type (optional, default: any, options: public, private)").Default(defaultConfig.AWSZoneType).EnumVar(&cfg.AWSZoneType, "", "public", "private")
app.Flag("aws-zone-tags", "When using the AWS provider, filter for zones with these tags").Default("").StringsVar(&cfg.AWSZoneTagFilter)
app.Flag("aws-profile", "When using the AWS provider, name of the profile to use").Default("").StringsVar(&cfg.AWSProfiles)
app.Flag("aws-assume-role", "When using the AWS API, assume this IAM role. Useful for hosted zones in another AWS account. Specify the full ARN, e.g. `arn:aws:iam::123455567:role/external-dns` (optional)").Default(defaultConfig.AWSAssumeRole).StringVar(&cfg.AWSAssumeRole)

View File

@ -78,7 +78,7 @@ type AWSSDProvider struct {
// only consider namespaces ending in this suffix
namespaceFilter *endpoint.DomainFilter
// filter namespace by type (private or public)
namespaceTypeFilter sdtypes.NamespaceFilter
namespaceTypeFilter []sdtypes.NamespaceFilter
// enables service without instances cleanup
cleanEmptyService bool
// filter services for removal
@ -102,21 +102,28 @@ func NewAWSSDProvider(domainFilter *endpoint.DomainFilter, namespaceType string,
return p, nil
}
// newSdNamespaceFilter initialized AWS SD Namespace Filter based on given string config
func newSdNamespaceFilter(namespaceTypeConfig string) sdtypes.NamespaceFilter {
// newSdNamespaceFilter returns NamespaceFilter based on the given namespace type configuration.
// If the config is "public", it filters for public namespaces; if "private", for private namespaces.
// For any other value (including empty), it returns filters for both public and private namespaces.
// ref: https://docs.aws.amazon.com/cloud-map/latest/api/API_ListNamespaces.html
func newSdNamespaceFilter(namespaceTypeConfig string) []sdtypes.NamespaceFilter {
switch namespaceTypeConfig {
case sdNamespaceTypePublic:
return sdtypes.NamespaceFilter{
Name: sdtypes.NamespaceFilterNameType,
Values: []string{string(sdtypes.NamespaceTypeDnsPublic)},
return []sdtypes.NamespaceFilter{
{
Name: sdtypes.NamespaceFilterNameType,
Values: []string{string(sdtypes.NamespaceTypeDnsPublic)},
},
}
case sdNamespaceTypePrivate:
return sdtypes.NamespaceFilter{
Name: sdtypes.NamespaceFilterNameType,
Values: []string{string(sdtypes.NamespaceTypeDnsPrivate)},
return []sdtypes.NamespaceFilter{
{
Name: sdtypes.NamespaceFilterNameType,
Values: []string{string(sdtypes.NamespaceTypeDnsPrivate)},
},
}
default:
return sdtypes.NamespaceFilter{}
return []sdtypes.NamespaceFilter{}
}
}
@ -354,7 +361,7 @@ func (p *AWSSDProvider) ListNamespaces(ctx context.Context) ([]*sdtypes.Namespac
namespaces := make([]*sdtypes.NamespaceSummary, 0)
paginator := sd.NewListNamespacesPaginator(p.client, &sd.ListNamespacesInput{
Filters: []sdtypes.NamespaceFilter{p.namespaceTypeFilter},
Filters: p.namespaceTypeFilter,
})
for paginator.HasMorePages() {
resp, err := paginator.NextPage(ctx)

View File

@ -254,14 +254,14 @@ func TestAWSSDProvider_ApplyChanges_Update(t *testing.T) {
ctx := context.Background()
// apply creates
provider.ApplyChanges(ctx, &plan.Changes{
_ = provider.ApplyChanges(ctx, &plan.Changes{
Create: oldEndpoints,
})
ctx = context.Background()
// apply update
provider.ApplyChanges(ctx, &plan.Changes{
_ = provider.ApplyChanges(ctx, &plan.Changes{
UpdateOld: oldEndpoints,
UpdateNew: newEndpoints,
})
@ -306,6 +306,7 @@ func TestAWSSDProvider_ListNamespaces(t *testing.T) {
}{
{"public filter", endpoint.NewDomainFilter([]string{}), "public", []*sdtypes.NamespaceSummary{namespaceToNamespaceSummary(namespaces["public"])}},
{"private filter", endpoint.NewDomainFilter([]string{}), "private", []*sdtypes.NamespaceSummary{namespaceToNamespaceSummary(namespaces["private"])}},
{"optional filter", endpoint.NewDomainFilter([]string{}), "", []*sdtypes.NamespaceSummary{namespaceToNamespaceSummary(namespaces["public"]), namespaceToNamespaceSummary(namespaces["private"])}},
{"domain filter", endpoint.NewDomainFilter([]string{"public.com"}), "", []*sdtypes.NamespaceSummary{namespaceToNamespaceSummary(namespaces["public"])}},
{"non-existing domain", endpoint.NewDomainFilter([]string{"xxx.com"}), "", []*sdtypes.NamespaceSummary{}},
} {
@ -913,7 +914,7 @@ func TestAWSSDProvider_RegisterInstance(t *testing.T) {
}
// AWS NLB instance (ALIAS)
provider.RegisterInstance(context.Background(), services["private"]["alias-srv"], &endpoint.Endpoint{
_ = provider.RegisterInstance(context.Background(), services["private"]["alias-srv"], &endpoint.Endpoint{
RecordType: endpoint.RecordTypeCNAME,
DNSName: "service1.private.com.",
RecordTTL: 300,
@ -927,7 +928,7 @@ func TestAWSSDProvider_RegisterInstance(t *testing.T) {
}
// CNAME instance
provider.RegisterInstance(context.Background(), services["private"]["cname-srv"], &endpoint.Endpoint{
_ = provider.RegisterInstance(context.Background(), services["private"]["cname-srv"], &endpoint.Endpoint{
RecordType: endpoint.RecordTypeCNAME,
DNSName: "service2.private.com.",
RecordTTL: 300,
@ -1001,7 +1002,7 @@ func TestAWSSDProvider_DeregisterInstance(t *testing.T) {
provider := newTestAWSSDProvider(api, endpoint.NewDomainFilter([]string{}), "", "")
provider.DeregisterInstance(context.Background(), services["private"]["srv1"], endpoint.NewEndpoint("srv1.private.com.", endpoint.RecordTypeA, "1.2.3.4"))
_ = provider.DeregisterInstance(context.Background(), services["private"]["srv1"], endpoint.NewEndpoint("srv1.private.com.", endpoint.RecordTypeA, "1.2.3.4"))
assert.Empty(t, instances["srv1"])
}