Skip to content

Commit

Permalink
feat: support for filtering by tags
Browse files Browse the repository at this point in the history
  • Loading branch information
rromic committed May 19, 2024
1 parent f0c574d commit 9a080cb
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 61 deletions.
60 changes: 44 additions & 16 deletions internal/service/acm/certificate_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta

input := &acm.ListCertificatesInput{}

//
if !tagsOk && !domainOk {
return diag.Errorf("no ACM Certificate matching search criteria. Please use at least domain or tags as search criteria")
}

if v, ok := d.GetOk("key_types"); ok && v.(*schema.Set).Len() > 0 {
input.Includes = &types.Filters{
KeyTypes: flex.ExpandStringyValueSet[types.KeyAlgorithm](v.(*schema.Set)),
Expand Down Expand Up @@ -129,6 +134,8 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta

var matchedCertificate *types.CertificateDetail

var matchedTagsCertificateTypes []*types.CertificateDetail

for _, arn := range arns {
input := &acm.DescribeCertificateInput{
CertificateArn: aws.String(arn),
Expand All @@ -149,9 +156,14 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta
certificateTagsIgnoreAWS := certificateTags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()

if len(certificateTagsIgnoreAWS) > 0 {
if tagsMatch(tags.(map[string]string), certificateTagsIgnoreAWS) {
if tagsMatch(tags.(map[string]interface{}), certificateTagsIgnoreAWS) {
if matchedCertificate == nil {
matchedCertificate = certificate

// If there is no filtering by certificate types, proceed to next certificate.
if len(certificateTypes) == 0 {
continue
}
}

// At this point, we already have a candidate certificate.
Expand All @@ -162,40 +174,49 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta
if err != nil {
return sdkdiag.AppendErrorf(diags, err)
}

// If there is no filtering by certificate types, proceed to next certificate.
if len(certificateTypes) == 0 {
continue
}
}

// If there is no filtering by certificate types, multiple certificates having same tags
// If there is no filtering by certificate types, multiple certificates having same tags.
if len(certificateTypes) == 0 {
// Now we have multiple candidate certificates and we only allow one certificate.
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching input criteria")
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching search criteria")
}
}

if !tagsMatch(tags.(map[string]interface{}), certificateTagsIgnoreAWS) {
continue
}
}

// If there is no filtering by certificate types, proceed to next certificate
// If there is need to further filtering by certificate types.
if len(certificateTypes) == 0 {
continue
}
}

if len(certificateTypes) > 0 {
for _, certificateType := range certificateTypes {
// If there is matched certificated by tags, setting matched certificate to nil
// we are ensuring that matched certificate should also have matched certificate type.
// If there is candidate filtered by tags, by setting matched certificate to nil
// we are ensuring that candidate needs to also match certificate type.
if tagsOk && matchedCertificate != nil {
matchedCertificate = nil
}

// If there is no matching by tags skip current certificate from further filtering.
if tagsOk && matchedCertificate == nil {
continue
}

if certificate.Type == certificateType {
// We do not have a candidate certificate.
if matchedCertificate == nil {
matchedCertificate = certificate

// If there is a candidate, store it for later checks if multiple candidates.
if tagsOk && !filterMostRecent {
matchedTagsCertificateTypes = append(matchedTagsCertificateTypes, certificate)
}

break
}

Expand All @@ -211,7 +232,7 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta
break
}
// Now we have multiple candidate certificates and we only allow one certificate.
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching input criteria")
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching search criteria")
}
}

Expand All @@ -238,11 +259,18 @@ func dataSourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta
}

// Now we have multiple candidate certificates and we only allow one certificate.
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching input criteria")

return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching search criteria")
}

// If there are multiple candidates with same tags and certificate types.
if len(matchedTagsCertificateTypes) > 1 {
// Now we have multiple candidate certificates and we only allow one certificate.
return sdkdiag.AppendErrorf(diags, "multiple ACM Certificates matching search criteria")
}

if matchedCertificate == nil {
return sdkdiag.AppendErrorf(diags, "no ACM Certificate found matching input criteria")
return sdkdiag.AppendErrorf(diags, "no ACM Certificate matching search criteria")
}

// Get the certificate data if the status is issued
Expand Down Expand Up @@ -303,13 +331,13 @@ func mostRecentCertificate(i, j *types.CertificateDetail) (*types.CertificateDet
return j, nil
}

func tagsMatch(tagsFilter, tagsCertificate map[string]string) bool {
func tagsMatch(tagsFilter map[string]interface{}, tagsCertificate map[string]string) bool {
if len(tagsFilter) > len(tagsCertificate) {
return false
}

for k, v := range tagsFilter {
if tagsCertificate[k] != v {
if tagsCertificate[k] != v.(string) {
return false
}
}
Expand Down
Loading

0 comments on commit 9a080cb

Please sign in to comment.