2022-05-04 19:24:19 +02:00
|
|
|
package ec2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
|
|
|
|
2022-05-05 09:59:28 +02:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/awsapi"
|
2022-05-04 19:24:19 +02:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
|
|
|
)
|
|
|
|
|
|
|
|
func getAZMap(cfg *apiConfig) map[string]string {
|
|
|
|
cfg.azMapLock.Lock()
|
|
|
|
defer cfg.azMapLock.Unlock()
|
|
|
|
|
|
|
|
if cfg.azMap != nil {
|
|
|
|
return cfg.azMap
|
|
|
|
}
|
|
|
|
|
|
|
|
azs, err := getAvailabilityZones(cfg)
|
|
|
|
cfg.azMap = make(map[string]string, len(azs))
|
|
|
|
if err != nil {
|
|
|
|
logger.Warnf("couldn't load availability zones map, so __meta_ec2_availability_zone_id label isn't set: %s", err)
|
|
|
|
return cfg.azMap
|
|
|
|
}
|
|
|
|
for _, az := range azs {
|
|
|
|
cfg.azMap[az.ZoneName] = az.ZoneID
|
|
|
|
}
|
|
|
|
return cfg.azMap
|
|
|
|
}
|
|
|
|
|
|
|
|
func getAvailabilityZones(cfg *apiConfig) ([]AvailabilityZone, error) {
|
|
|
|
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
2022-05-06 11:43:29 +02:00
|
|
|
azFilters := awsapi.GetFiltersQueryString(cfg.azFilters, azFiltersWhitelist)
|
2022-05-05 09:59:28 +02:00
|
|
|
data, err := cfg.awsConfig.GetEC2APIResponse("DescribeAvailabilityZones", azFilters, "")
|
2022-05-04 19:24:19 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot obtain availability zones: %w", err)
|
|
|
|
}
|
|
|
|
azr, err := parseAvailabilityZonesResponse(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot parse availability zones list: %w", err)
|
|
|
|
}
|
|
|
|
return azr.AvailabilityZoneInfo.Items, nil
|
|
|
|
}
|
|
|
|
|
2022-05-05 09:59:28 +02:00
|
|
|
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
|
|
|
var azFiltersWhitelist = map[string]bool{
|
|
|
|
"group-name": true,
|
|
|
|
"message": true,
|
|
|
|
"opt-in-status": true,
|
|
|
|
"parent-zoneID": true,
|
|
|
|
"parent-zoneName": true,
|
|
|
|
"region-name": true,
|
|
|
|
"state": true,
|
|
|
|
"zone-id": true,
|
|
|
|
"zone-type": true,
|
|
|
|
"zone-name": true,
|
|
|
|
}
|
|
|
|
|
2022-05-04 19:24:19 +02:00
|
|
|
// AvailabilityZonesResponse represents the response for https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
|
|
|
type AvailabilityZonesResponse struct {
|
|
|
|
AvailabilityZoneInfo AvailabilityZoneInfo `xml:"availabilityZoneInfo"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// AvailabilityZoneInfo represents availabilityZoneInfo for https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
|
|
|
type AvailabilityZoneInfo struct {
|
|
|
|
Items []AvailabilityZone `xml:"item"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// AvailabilityZone represents availabilityZone for https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AvailabilityZone.html
|
|
|
|
type AvailabilityZone struct {
|
|
|
|
ZoneName string `xml:"zoneName"`
|
|
|
|
ZoneID string `xml:"zoneId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseAvailabilityZonesResponse(data []byte) (*AvailabilityZonesResponse, error) {
|
|
|
|
var v AvailabilityZonesResponse
|
|
|
|
if err := xml.Unmarshal(data, &v); err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot unmarshal DescribeAvailabilityZonesResponse from %q: %w", data, err)
|
|
|
|
}
|
|
|
|
return &v, nil
|
|
|
|
}
|