Skip to content
This repository has been archived by the owner on Aug 16, 2022. It is now read-only.

feat/ignore unsupported regions errors #214

Merged
merged 6 commits into from
Oct 21, 2021
Merged
Changes from 2 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
79 changes: 79 additions & 0 deletions client/helpers.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,97 @@
package client

import (
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"regexp"
"strings"
"sync"

"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/smithy-go"
)

const supportedServicesLink = "https://api.regional-table.region-services.aws.a2z.com/index.json"

//log-group:([a-zA-Z0-9/]+):
var GroupNameRegex = regexp.MustCompile("arn:aws:logs:[a-z0-9-]+:[0-9]+:log-group:([a-zA-Z0-9-/]+):")

type SupportedServicesData struct {
Prices []struct {
Attributes struct {
Region string `json:"aws:region"`
Service string `json:"aws:serviceName"`
} `json:"attributes"`
Id string `json:"id"`
} `json:"prices"`
}

// supportedServices map of the supported service-regions
var supportedServices map[string]map[string]struct{}
var getSupportedServices sync.Once

// apiErrorServiceNames stores api subdomains and service names for error decoding
var apiErrorServiceNames = map[string]string{
"mq": "Amazon MQ",
"cognito-identity": "Amazon Cognito",
"cognito-idp": "Amazon Cognito",
"ec2": "Amazon Elastic Compute Cloud (EC2)",
}

func downloadSupportedResourcesForRegions() (map[string]map[string]struct{}, error) {
amanenk marked this conversation as resolved.
Show resolved Hide resolved
req, err := http.NewRequest(http.MethodGet, supportedServicesLink, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get aws supported resources for region, status code: %d", resp.StatusCode)
}

var data SupportedServicesData
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, err
}

m := make(map[string]map[string]struct{})
for _, p := range data.Prices {
if _, ok := m[p.Attributes.Service]; !ok {
m[p.Attributes.Service] = make(map[string]struct{})
}
m[p.Attributes.Service][p.Attributes.Region] = struct{}{}
}

return m, nil
}

func ignoreUnsupportedResourceForRegionError(err error) bool {
amanenk marked this conversation as resolved.
Show resolved Hide resolved
getSupportedServices.Do(func() {
supportedServices, _ = downloadSupportedResourcesForRegions()
})
var dnsErr *net.DNSError
if supportedServices != nil && errors.As(err, &dnsErr) && dnsErr.IsNotFound {
parts := strings.Split(dnsErr.Name, ".")
apiService := apiErrorServiceNames[parts[0]]
region := parts[1]
_, ok := supportedServices[apiService][region]
amanenk marked this conversation as resolved.
Show resolved Hide resolved
// if service-region combination is in the map than service is supported and error should not be ignored
return ok
}
return true
}

func IgnoreAccessDeniedServiceDisabled(err error) bool {
if ignoreUnsupportedResourceForRegionError(err) {
return true
}
var ae smithy.APIError
if errors.As(err, &ae) {
switch ae.ErrorCode() {
Expand Down