mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/promscrape/discovery/ec2: properly pass filters to DescribeAvailabilityZones API call
Previously filters wheren't passed to this call after the commit 0e09fdb8b0
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1626
This commit is contained in:
parent
d285c2fea7
commit
97f9c2f667
5 changed files with 57 additions and 35 deletions
|
@ -87,6 +87,7 @@ func NewConfig(region, roleARN, accessKey, secretKey string) (*Config, error) {
|
|||
// GetEC2APIResponse performs EC2 API request with ghe given action.
|
||||
//
|
||||
// filtersQueryString must contain an optional percent-encoded query string for aws filters.
|
||||
// This string can be obtained by calling GetFiltersQueryString().
|
||||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html for examples.
|
||||
// See also https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Filter.html
|
||||
func (cfg *Config) GetEC2APIResponse(action, filtersQueryString, nextPageToken string) ([]byte, error) {
|
||||
|
@ -424,3 +425,30 @@ func buildAPIEndpoint(customEndpoint, region, service string) string {
|
|||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
// GetFiltersQueryString returns query string formed from the given filters.
|
||||
//
|
||||
// If whitelist isn't nil, then filters which don't fall into whitelist isn't returned.
|
||||
func GetFiltersQueryString(filters []Filter, whitelist map[string]bool) string {
|
||||
// See how to build filters query string at examples at https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html
|
||||
var args []string
|
||||
for i, f := range filters {
|
||||
if whitelist != nil && !whitelist[f.Name] {
|
||||
continue
|
||||
}
|
||||
args = append(args, fmt.Sprintf("Filter.%d.Name=%s", i+1, url.QueryEscape(f.Name)))
|
||||
for j, v := range f.Values {
|
||||
args = append(args, fmt.Sprintf("Filter.%d.Value.%d=%s", i+1, j+1, url.QueryEscape(v)))
|
||||
}
|
||||
}
|
||||
return strings.Join(args, "&")
|
||||
}
|
||||
|
||||
// Filter is ec2 filter.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html
|
||||
// and https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Filter.html
|
||||
type Filter struct {
|
||||
Name string `yaml:"name"`
|
||||
Values []string `yaml:"values"`
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package ec2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/awsapi"
|
||||
|
@ -11,9 +8,9 @@ import (
|
|||
)
|
||||
|
||||
type apiConfig struct {
|
||||
awsConfig *awsapi.Config
|
||||
filtersQueryString string
|
||||
port int
|
||||
awsConfig *awsapi.Config
|
||||
filters []awsapi.Filter
|
||||
port int
|
||||
|
||||
// A map from AZ name to AZ id.
|
||||
azMap map[string]string
|
||||
|
@ -31,7 +28,6 @@ func getAPIConfig(sdc *SDConfig) (*apiConfig, error) {
|
|||
}
|
||||
|
||||
func newAPIConfig(sdc *SDConfig) (*apiConfig, error) {
|
||||
fqs := getFiltersQueryString(sdc.Filters)
|
||||
port := 80
|
||||
if sdc.Port != nil {
|
||||
port = *sdc.Port
|
||||
|
@ -41,21 +37,9 @@ func newAPIConfig(sdc *SDConfig) (*apiConfig, error) {
|
|||
return nil, err
|
||||
}
|
||||
cfg := &apiConfig{
|
||||
awsConfig: awsCfg,
|
||||
filtersQueryString: fqs,
|
||||
port: port,
|
||||
awsConfig: awsCfg,
|
||||
filters: sdc.Filters,
|
||||
port: port,
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func getFiltersQueryString(filters []Filter) string {
|
||||
// See how to build filters query string at examples at https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html
|
||||
var args []string
|
||||
for i, f := range filters {
|
||||
args = append(args, fmt.Sprintf("Filter.%d.Name=%s", i+1, url.QueryEscape(f.Name)))
|
||||
for j, v := range f.Values {
|
||||
args = append(args, fmt.Sprintf("Filter.%d.Value.%d=%s", i+1, j+1, url.QueryEscape(v)))
|
||||
}
|
||||
}
|
||||
return strings.Join(args, "&")
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/awsapi"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
)
|
||||
|
||||
|
@ -29,7 +30,8 @@ func getAZMap(cfg *apiConfig) map[string]string {
|
|||
|
||||
func getAvailabilityZones(cfg *apiConfig) ([]AvailabilityZone, error) {
|
||||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
||||
data, err := cfg.awsConfig.GetEC2APIResponse("DescribeAvailabilityZones", "", "")
|
||||
azFilters := awsapi.GetFiltersQueryString(cfg.filters, azFiltersWhitelist)
|
||||
data, err := cfg.awsConfig.GetEC2APIResponse("DescribeAvailabilityZones", azFilters, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot obtain availability zones: %w", err)
|
||||
}
|
||||
|
@ -40,6 +42,20 @@ func getAvailabilityZones(cfg *apiConfig) ([]AvailabilityZone, error) {
|
|||
return azr.AvailabilityZoneInfo.Items, nil
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
// AvailabilityZonesResponse represents the response for https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html
|
||||
type AvailabilityZonesResponse struct {
|
||||
AvailabilityZoneInfo AvailabilityZoneInfo `xml:"availabilityZoneInfo"`
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/awsapi"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
||||
)
|
||||
|
||||
|
@ -26,17 +27,8 @@ type SDConfig struct {
|
|||
RoleARN string `yaml:"role_arn,omitempty"`
|
||||
// RefreshInterval time.Duration `yaml:"refresh_interval"`
|
||||
// refresh_interval is obtained from `-promscrape.ec2SDCheckInterval` command-line option.
|
||||
Port *int `yaml:"port,omitempty"`
|
||||
Filters []Filter `yaml:"filters,omitempty"`
|
||||
}
|
||||
|
||||
// Filter is ec2 filter.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html
|
||||
// and https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Filter.html
|
||||
type Filter struct {
|
||||
Name string `yaml:"name"`
|
||||
Values []string `yaml:"values"`
|
||||
Port *int `yaml:"port,omitempty"`
|
||||
Filters []awsapi.Filter `yaml:"filters,omitempty"`
|
||||
}
|
||||
|
||||
// GetLabels returns ec2 labels according to sdc.
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/awsapi"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||
)
|
||||
|
||||
|
@ -28,8 +29,9 @@ func getReservations(cfg *apiConfig) ([]Reservation, error) {
|
|||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html
|
||||
var rs []Reservation
|
||||
pageToken := ""
|
||||
instanceFilters := awsapi.GetFiltersQueryString(cfg.filters, nil)
|
||||
for {
|
||||
data, err := cfg.awsConfig.GetEC2APIResponse("DescribeInstances", cfg.filtersQueryString, pageToken)
|
||||
data, err := cfg.awsConfig.GetEC2APIResponse("DescribeInstances", instanceFilters, pageToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot obtain instances: %w", err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue