mirror of
https://github.com/prometheus/prometheus.git
synced 2026-05-05 04:16:15 +02:00
AWS SD: RDS Role (#18206)
This commit is contained in:
parent
b9ce7f3be0
commit
5a02b92c0e
5
cmd/prometheus/testdata/features.json
vendored
5
cmd/prometheus/testdata/features.json
vendored
@ -140,13 +140,13 @@
|
||||
"-": true,
|
||||
"/": true,
|
||||
"<": true,
|
||||
"</": true,
|
||||
"<=": true,
|
||||
"==": true,
|
||||
"=~": true,
|
||||
">": true,
|
||||
">=": true,
|
||||
">/": true,
|
||||
"</": true,
|
||||
">=": true,
|
||||
"@": true,
|
||||
"^": true,
|
||||
"and": true,
|
||||
@ -206,6 +206,7 @@
|
||||
"openstack": true,
|
||||
"ovhcloud": true,
|
||||
"puppetdb": true,
|
||||
"rds": true,
|
||||
"scaleway": true,
|
||||
"serverset": true,
|
||||
"stackit": true,
|
||||
|
||||
@ -48,6 +48,7 @@ const (
|
||||
RoleElasticache Role = "elasticache"
|
||||
RoleLightsail Role = "lightsail"
|
||||
RoleMSK Role = "msk"
|
||||
RoleRDS Role = "rds"
|
||||
)
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
@ -56,7 +57,7 @@ func (c *Role) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
return err
|
||||
}
|
||||
switch *c {
|
||||
case RoleEC2, RoleECS, RoleElasticache, RoleLightsail, RoleMSK:
|
||||
case RoleEC2, RoleECS, RoleElasticache, RoleLightsail, RoleMSK, RoleRDS:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unknown AWS SD role %q", *c)
|
||||
@ -92,6 +93,7 @@ type SDConfig struct {
|
||||
*ElasticacheSDConfig `yaml:"-"`
|
||||
*LightsailSDConfig `yaml:"-"`
|
||||
*MSKSDConfig `yaml:"-"`
|
||||
*RDSSDConfig `yaml:"-"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface for SDConfig.
|
||||
@ -264,6 +266,37 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
if c.Clusters != nil {
|
||||
c.MSKSDConfig.Clusters = c.Clusters
|
||||
}
|
||||
case RoleRDS:
|
||||
if c.RDSSDConfig == nil {
|
||||
rdsConfig := DefaultRDSSDConfig
|
||||
c.RDSSDConfig = &rdsConfig
|
||||
}
|
||||
c.RDSSDConfig.HTTPClientConfig = c.HTTPClientConfig
|
||||
c.RDSSDConfig.Region = c.Region
|
||||
if c.Endpoint != "" {
|
||||
c.RDSSDConfig.Endpoint = c.Endpoint
|
||||
}
|
||||
if c.AccessKey != "" {
|
||||
c.RDSSDConfig.AccessKey = c.AccessKey
|
||||
}
|
||||
if c.SecretKey != "" {
|
||||
c.RDSSDConfig.SecretKey = c.SecretKey
|
||||
}
|
||||
if c.Profile != "" {
|
||||
c.RDSSDConfig.Profile = c.Profile
|
||||
}
|
||||
if c.RoleARN != "" {
|
||||
c.RDSSDConfig.RoleARN = c.RoleARN
|
||||
}
|
||||
if c.Port != 0 {
|
||||
c.RDSSDConfig.Port = c.Port
|
||||
}
|
||||
if c.RefreshInterval != 0 {
|
||||
c.RDSSDConfig.RefreshInterval = c.RefreshInterval
|
||||
}
|
||||
if c.Clusters != nil {
|
||||
c.RDSSDConfig.Clusters = c.Clusters
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown AWS SD role %q", c.Role)
|
||||
}
|
||||
@ -301,6 +334,9 @@ func (c *SDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Di
|
||||
case RoleMSK:
|
||||
opts.Metrics = &mskMetrics{refreshMetrics: awsMetrics.refreshMetrics}
|
||||
return NewMSKDiscovery(c.MSKSDConfig, opts)
|
||||
case RoleRDS:
|
||||
opts.Metrics = &rdsMetrics{refreshMetrics: awsMetrics.refreshMetrics}
|
||||
return NewRDSDiscovery(c.RDSSDConfig, opts)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown AWS SD role %q", c.Role)
|
||||
}
|
||||
|
||||
32
discovery/aws/metrics_rds.go
Normal file
32
discovery/aws/metrics_rds.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"github.com/prometheus/prometheus/discovery"
|
||||
)
|
||||
|
||||
type rdsMetrics struct {
|
||||
refreshMetrics discovery.RefreshMetricsInstantiator
|
||||
}
|
||||
|
||||
var _ discovery.DiscovererMetrics = (*rdsMetrics)(nil)
|
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (*rdsMetrics) Register() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (*rdsMetrics) Unregister() {}
|
||||
999
discovery/aws/rds.go
Normal file
999
discovery/aws/rds.go
Normal file
@ -0,0 +1,999 @@
|
||||
// Copyright The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
awsConfig "github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
|
||||
"github.com/aws/aws-sdk-go-v2/service/rds"
|
||||
"github.com/aws/aws-sdk-go-v2/service/rds/types"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sts"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/config"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/prometheus/common/promslog"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/prometheus/prometheus/discovery"
|
||||
"github.com/prometheus/prometheus/discovery/refresh"
|
||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||
"github.com/prometheus/prometheus/util/strutil"
|
||||
)
|
||||
|
||||
const (
|
||||
rdsLabel = model.MetaLabelPrefix + "rds_"
|
||||
|
||||
// DB cluster labels.
|
||||
rdsLabelCluster = rdsLabel + "cluster_"
|
||||
rdsLabelClusterActivityStreamKinesisStreamName = rdsLabelCluster + "activity_stream_kinesis_stream_name"
|
||||
rdsLabelClusterActivityStreamKMSKeyID = rdsLabelCluster + "activity_stream_kms_key_id"
|
||||
rdsLabelClusterActivityStreamMode = rdsLabelCluster + "activity_stream_mode"
|
||||
rdsLabelClusterActivityStreamStatus = rdsLabelCluster + "activity_stream_status"
|
||||
rdsLabelClusterAllocatedStorage = rdsLabelCluster + "allocated_storage"
|
||||
rdsLabelClusterAutoMinorVersionUpgrade = rdsLabelCluster + "auto_minor_version_upgrade"
|
||||
rdsLabelClusterAutomaticRestartTime = rdsLabelCluster + "automatic_restart_time"
|
||||
rdsLabelClusterAwsBackupRecoveryPointArn = rdsLabelCluster + "aws_backup_recovery_point_arn"
|
||||
rdsLabelClusterBacktrackConsumedChangeRecords = rdsLabelCluster + "backtrack_consumed_change_records"
|
||||
rdsLabelClusterBacktrackWindow = rdsLabelCluster + "backtrack_window"
|
||||
rdsLabelClusterBackupRetentionPeriod = rdsLabelCluster + "backup_retention_period"
|
||||
rdsLabelClusterCapacity = rdsLabelCluster + "capacity"
|
||||
rdsLabelClusterCharacterSetName = rdsLabelCluster + "character_set_name"
|
||||
rdsLabelClusterCloneGroupID = rdsLabelCluster + "clone_group_id"
|
||||
rdsLabelClusterClusterCreateTime = rdsLabelCluster + "cluster_create_time"
|
||||
rdsLabelClusterClusterScalabilityType = rdsLabelCluster + "cluster_scalability_type"
|
||||
rdsLabelClusterCopyTagsToSnapshot = rdsLabelCluster + "copy_tags_to_snapshot"
|
||||
rdsLabelClusterCrossAccountClone = rdsLabelCluster + "cross_account_clone"
|
||||
rdsLabelClusterDBClusterArn = rdsLabelCluster + "arn"
|
||||
rdsLabelClusterDBClusterIdentifier = rdsLabelCluster + "identifier"
|
||||
rdsLabelClusterDBClusterInstanceClass = rdsLabelCluster + "instance_class"
|
||||
rdsLabelClusterDBClusterParameterGroup = rdsLabelCluster + "parameter_group"
|
||||
rdsLabelClusterDBSubnetGroup = rdsLabelCluster + "subnet_group"
|
||||
rdsLabelClusterDBSystemID = rdsLabelCluster + "db_system_id"
|
||||
rdsLabelClusterDatabaseInsightsMode = rdsLabelCluster + "database_insights_mode"
|
||||
rdsLabelClusterDatabaseName = rdsLabelCluster + "database_name"
|
||||
rdsLabelClusterDBClusterResourceID = rdsLabelCluster + "resource_id"
|
||||
rdsLabelClusterDeletionProtection = rdsLabelCluster + "deletion_protection"
|
||||
rdsLabelClusterEarliestBacktrackTime = rdsLabelCluster + "earliest_backtrack_time"
|
||||
rdsLabelClusterEarliestRestorableTime = rdsLabelCluster + "earliest_restorable_time"
|
||||
rdsLabelClusterEndpoint = rdsLabelCluster + "endpoint"
|
||||
rdsLabelClusterEngine = rdsLabelCluster + "engine"
|
||||
rdsLabelClusterEngineLifecycleSupport = rdsLabelCluster + "engine_lifecycle_support"
|
||||
rdsLabelClusterEngineMode = rdsLabelCluster + "engine_mode"
|
||||
rdsLabelClusterEngineVersion = rdsLabelCluster + "engine_version"
|
||||
rdsLabelClusterGlobalClusterIdentifier = rdsLabelCluster + "global_cluster_identifier"
|
||||
rdsLabelClusterGlobalWriteForwardingRequested = rdsLabelCluster + "global_write_forwarding_requested"
|
||||
rdsLabelClusterGlobalWriteForwardingStatus = rdsLabelCluster + "global_write_forwarding_status"
|
||||
rdsLabelClusterHostedZoneID = rdsLabelCluster + "hosted_zone_id"
|
||||
rdsLabelClusterHTTPEndpointEnabled = rdsLabelCluster + "http_endpoint_enabled"
|
||||
rdsLabelClusterIAMDatabaseAuthenticationEnabled = rdsLabelCluster + "iam_database_authentication_enabled"
|
||||
rdsLabelClusterIOOptimizedNextAllowedModificationTime = rdsLabelCluster + "io_optimized_next_allowed_modification_time"
|
||||
rdsLabelClusterIops = rdsLabelCluster + "iops"
|
||||
rdsLabelClusterKMSKeyID = rdsLabelCluster + "kms_key_id"
|
||||
rdsLabelClusterLatestRestorableTime = rdsLabelCluster + "latest_restorable_time"
|
||||
rdsLabelClusterLocalWriteForwardingStatus = rdsLabelCluster + "local_write_forwarding_status"
|
||||
rdsLabelClusterMasterUsername = rdsLabelCluster + "master_username"
|
||||
rdsLabelClusterMonitoringInterval = rdsLabelCluster + "monitoring_interval"
|
||||
rdsLabelClusterMonitoringRoleArn = rdsLabelCluster + "monitoring_role_arn"
|
||||
rdsLabelClusterMultiAZ = rdsLabelCluster + "multi_az"
|
||||
rdsLabelClusterNetworkType = rdsLabelCluster + "network_type"
|
||||
rdsLabelClusterPercentProgress = rdsLabelCluster + "percent_progress"
|
||||
rdsLabelClusterPerformanceInsightsEnabled = rdsLabelCluster + "performance_insights_enabled"
|
||||
rdsLabelClusterPerformanceInsightsKMSKeyID = rdsLabelCluster + "performance_insights_kms_key_id"
|
||||
rdsLabelClusterPerformanceInsightsRetentionPeriod = rdsLabelCluster + "performance_insights_retention_period"
|
||||
rdsLabelClusterPort = rdsLabelCluster + "port"
|
||||
rdsLabelClusterPreferredBackupWindow = rdsLabelCluster + "preferred_backup_window"
|
||||
rdsLabelClusterPreferredMaintenanceWindow = rdsLabelCluster + "preferred_maintenance_window"
|
||||
rdsLabelClusterPubliclyAccessible = rdsLabelCluster + "publicly_accessible"
|
||||
rdsLabelClusterReaderEndpoint = rdsLabelCluster + "reader_endpoint"
|
||||
rdsLabelClusterReplicationSourceIdentifier = rdsLabelCluster + "replication_source_identifier"
|
||||
rdsLabelClusterServerlessV2PlatformVersion = rdsLabelCluster + "serverless_v2_platform_version"
|
||||
rdsLabelClusterStatus = rdsLabelCluster + "status"
|
||||
rdsLabelClusterStorageEncrypted = rdsLabelCluster + "storage_encrypted"
|
||||
rdsLabelClusterStorageEncryptionType = rdsLabelCluster + "storage_encryption_type"
|
||||
rdsLabelClusterStorageThroughput = rdsLabelCluster + "storage_throughput"
|
||||
rdsLabelClusterStorageType = rdsLabelCluster + "storage_type"
|
||||
rdsLabelClusterUpgradeRolloutOrder = rdsLabelCluster + "upgrade_rollout_order"
|
||||
|
||||
// DB cluster tags - create one label per tag key, with the format: rds_cluster_tag_<tagkey>.
|
||||
rdsLabelClusterTag = rdsLabelCluster + "tag_"
|
||||
|
||||
// DB instance labels.
|
||||
rdsLabelInstance = rdsLabel + "instance_"
|
||||
rdsLabelInstanceIsClusterWriter = rdsLabelInstance + "is_cluster_writer"
|
||||
rdsLabelInstanceActivityStreamEngineNativeAuditFieldsIncluded = rdsLabelInstance + "activity_stream_engine_native_audit_fields_included"
|
||||
rdsLabelInstanceActivityStreamKinesisStreamName = rdsLabelInstance + "activity_stream_kinesis_stream_name"
|
||||
rdsLabelInstanceActivityStreamKmsKeyID = rdsLabelInstance + "activity_stream_kms_key_id"
|
||||
rdsLabelInstanceActivityStreamMode = rdsLabelInstance + "activity_stream_mode"
|
||||
rdsLabelInstanceActivityStreamPolicyStatus = rdsLabelInstance + "activity_stream_policy_status"
|
||||
rdsLabelInstanceActivityStreamStatus = rdsLabelInstance + "activity_stream_status"
|
||||
rdsLabelInstanceAllocatedStorage = rdsLabelInstance + "allocated_storage"
|
||||
rdsLabelInstanceAutoMinorVersionUpgrade = rdsLabelInstance + "auto_minor_version_upgrade"
|
||||
rdsLabelInstanceAutomaticRestartTime = rdsLabelInstance + "automatic_restart_time"
|
||||
rdsLabelInstanceAutomationMode = rdsLabelInstance + "automation_mode"
|
||||
rdsLabelInstanceAvailabilityZone = rdsLabelInstance + "availability_zone"
|
||||
rdsLabelInstanceAwsBackupRecoveryPointArn = rdsLabelInstance + "aws_backup_recovery_point_arn"
|
||||
rdsLabelInstanceBackupRetentionPeriod = rdsLabelInstance + "backup_retention_period"
|
||||
rdsLabelInstanceBackupTarget = rdsLabelInstance + "backup_target"
|
||||
rdsLabelInstanceCACertificateIdentifier = rdsLabelInstance + "ca_certificate_identifier"
|
||||
rdsLabelInstanceCharacterSetName = rdsLabelInstance + "character_set_name"
|
||||
rdsLabelInstanceCopyTagsToSnapshot = rdsLabelInstance + "copy_tags_to_snapshot"
|
||||
rdsLabelInstanceCustomIamInstanceProfile = rdsLabelInstance + "custom_iam_instance_profile"
|
||||
rdsLabelInstanceCustomerOwnedIPEnabled = rdsLabelInstance + "customer_owned_ip_enabled"
|
||||
rdsLabelInstanceDBClusterIdentifier = rdsLabelInstance + "db_cluster_identifier"
|
||||
rdsLabelInstanceDBInstanceArn = rdsLabelInstance + "arn"
|
||||
rdsLabelInstanceDBInstanceClass = rdsLabelInstance + "class"
|
||||
rdsLabelInstanceDBInstanceIdentifier = rdsLabelInstance + "identifier"
|
||||
rdsLabelInstanceDBInstanceStatus = rdsLabelInstance + "status"
|
||||
rdsLabelInstanceDBName = rdsLabelInstance + "db_name"
|
||||
rdsLabelInstanceDBSubnetGroup = rdsLabelInstance + "subnet_group"
|
||||
rdsLabelInstanceDBSystemID = rdsLabelInstance + "db_system_id"
|
||||
rdsLabelInstanceDatabaseInsightsMode = rdsLabelInstance + "database_insights_mode"
|
||||
rdsLabelInstanceDBInstancePort = rdsLabelInstance + "port"
|
||||
rdsLabelInstanceDBResourceID = rdsLabelInstance + "resource_id"
|
||||
rdsLabelInstanceDedicatedLogVolume = rdsLabelInstance + "dedicated_log_volume"
|
||||
rdsLabelInstanceDeletionProtection = rdsLabelInstance + "deletion_protection"
|
||||
rdsLabelInstanceEndpointAddress = rdsLabelInstance + "endpoint_address"
|
||||
rdsLabelInstanceEndpointHostedZoneID = rdsLabelInstance + "endpoint_hosted_zone_id"
|
||||
rdsLabelInstanceEndpointPort = rdsLabelInstance + "endpoint_port"
|
||||
rdsLabelInstanceEngine = rdsLabelInstance + "engine"
|
||||
rdsLabelInstanceEngineLifecycleSupport = rdsLabelInstance + "engine_lifecycle_support"
|
||||
rdsLabelInstanceEngineVersion = rdsLabelInstance + "engine_version"
|
||||
rdsLabelInstanceEnhancedMonitoringResourceArn = rdsLabelInstance + "enhanced_monitoring_resource_arn"
|
||||
rdsLabelInstanceIAMDatabaseAuthenticationEnabled = rdsLabelInstance + "iam_database_authentication_enabled"
|
||||
rdsLabelInstanceInstanceCreateTime = rdsLabelInstance + "instance_create_time"
|
||||
rdsLabelInstanceIops = rdsLabelInstance + "iops"
|
||||
rdsLabelInstanceIsStorageConfigUpgradeAvailable = rdsLabelInstance + "is_storage_config_upgrade_available"
|
||||
rdsLabelInstanceKMSKeyID = rdsLabelInstance + "kms_key_id"
|
||||
rdsLabelInstanceLatestRestorableTime = rdsLabelInstance + "latest_restorable_time"
|
||||
rdsLabelInstanceLicenseModel = rdsLabelInstance + "license_model"
|
||||
rdsLabelInstanceListenerEndpointAddress = rdsLabelInstance + "listener_endpoint_address"
|
||||
rdsLabelInstanceListenerEndpointHostedZoneID = rdsLabelInstance + "listener_endpoint_hosted_zone_id"
|
||||
rdsLabelInstanceListenerEndpointPort = rdsLabelInstance + "listener_endpoint_port"
|
||||
rdsLabelInstanceMasterUsername = rdsLabelInstance + "master_username"
|
||||
rdsLabelInstanceMaxAllocatedStorage = rdsLabelInstance + "max_allocated_storage"
|
||||
rdsLabelInstanceMonitoringInterval = rdsLabelInstance + "monitoring_interval"
|
||||
rdsLabelInstanceMonitoringRoleArn = rdsLabelInstance + "monitoring_role_arn"
|
||||
rdsLabelInstanceMultiAZ = rdsLabelInstance + "multi_az"
|
||||
rdsLabelInstanceMultiTenant = rdsLabelInstance + "multi_tenant"
|
||||
rdsLabelInstanceNcharCharacterSetName = rdsLabelInstance + "nchar_character_set_name"
|
||||
rdsLabelInstanceNetworkType = rdsLabelInstance + "network_type"
|
||||
rdsLabelInstancePercentProgress = rdsLabelInstance + "percent_progress"
|
||||
rdsLabelInstancePerformanceInsightsEnabled = rdsLabelInstance + "performance_insights_enabled"
|
||||
rdsLabelInstancePerformanceInsightsKMSKeyID = rdsLabelInstance + "performance_insights_kms_key_id"
|
||||
rdsLabelInstancePerformanceInsightsRetentionPeriod = rdsLabelInstance + "performance_insights_retention_period"
|
||||
rdsLabelInstancePreferredBackupWindow = rdsLabelInstance + "preferred_backup_window"
|
||||
rdsLabelInstancePreferredMaintenanceWindow = rdsLabelInstance + "preferred_maintenance_window"
|
||||
rdsLabelInstancePromotionTier = rdsLabelInstance + "promotion_tier"
|
||||
rdsLabelInstancePubliclyAccessible = rdsLabelInstance + "publicly_accessible"
|
||||
rdsLabelInstanceReadReplicaSourceDBClusterIdentifier = rdsLabelInstance + "read_replica_source_db_cluster_identifier"
|
||||
rdsLabelInstanceReadReplicaSourceDBInstanceIdentifier = rdsLabelInstance + "read_replica_source_db_instance_identifier"
|
||||
rdsLabelInstanceReplicaMode = rdsLabelInstance + "replica_mode"
|
||||
rdsLabelInstanceResumeFullAutomationModeTime = rdsLabelInstance + "resume_full_automation_mode_time"
|
||||
rdsLabelInstanceSecondaryAvailabilityZone = rdsLabelInstance + "secondary_availability_zone"
|
||||
rdsLabelInstanceStorageEncrypted = rdsLabelInstance + "storage_encrypted"
|
||||
rdsLabelInstanceStorageEncryptionType = rdsLabelInstance + "storage_encryption_type"
|
||||
rdsLabelInstanceStorageThroughput = rdsLabelInstance + "storage_throughput"
|
||||
rdsLabelInstanceStorageType = rdsLabelInstance + "storage_type"
|
||||
rdsLabelInstanceStorageVolumeStatus = rdsLabelInstance + "storage_volume_status"
|
||||
rdsLabelInstanceTdeCredentialArn = rdsLabelInstance + "tde_credential_arn"
|
||||
rdsLabelInstanceTimezone = rdsLabelInstance + "timezone"
|
||||
rdsLabelInstanceUpgradeRolloutOrder = rdsLabelInstance + "upgrade_rollout_order"
|
||||
|
||||
// DB instance tags - create one label per tag key, with the format: rds_instance_tag_<tagkey>.
|
||||
rdsLabelInstanceTag = rdsLabelInstance + "tag_"
|
||||
)
|
||||
|
||||
// DefaultRDSSDConfig is the default RDS SD configuration.
|
||||
var DefaultRDSSDConfig = RDSSDConfig{
|
||||
Port: 80,
|
||||
RefreshInterval: model.Duration(60 * time.Second),
|
||||
RequestConcurrency: 10,
|
||||
HTTPClientConfig: config.DefaultHTTPClientConfig,
|
||||
}
|
||||
|
||||
func init() {
|
||||
discovery.RegisterConfig(&RDSSDConfig{})
|
||||
}
|
||||
|
||||
// RDSSDConfig is the configuration for RDS based service discovery.
|
||||
type RDSSDConfig struct {
|
||||
Region string `yaml:"region"`
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
AccessKey string `yaml:"access_key,omitempty"`
|
||||
SecretKey config.Secret `yaml:"secret_key,omitempty"`
|
||||
Profile string `yaml:"profile,omitempty"`
|
||||
RoleARN string `yaml:"role_arn,omitempty"`
|
||||
Clusters []string `yaml:"clusters,omitempty"`
|
||||
Port int `yaml:"port"`
|
||||
RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"`
|
||||
|
||||
RequestConcurrency int `yaml:"request_concurrency,omitempty"`
|
||||
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
|
||||
}
|
||||
|
||||
// NewDiscovererMetrics implements discovery.Config.
|
||||
func (*RDSSDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics {
|
||||
return &rdsMetrics{
|
||||
refreshMetrics: rmi,
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name of the RDS Config.
|
||||
func (*RDSSDConfig) Name() string { return "rds" }
|
||||
|
||||
// NewDiscoverer returns a Discoverer for the RDS Config.
|
||||
func (c *RDSSDConfig) NewDiscoverer(opts discovery.DiscovererOptions) (discovery.Discoverer, error) {
|
||||
return NewRDSDiscovery(c, opts)
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface for the RDS Config.
|
||||
func (c *RDSSDConfig) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
*c = DefaultRDSSDConfig
|
||||
type plain RDSSDConfig
|
||||
err := unmarshal((*plain)(c))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Region, err = loadRegion(context.Background(), c.Region)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine AWS region: %w", err)
|
||||
}
|
||||
|
||||
return c.HTTPClientConfig.Validate()
|
||||
}
|
||||
|
||||
type rdsClient interface {
|
||||
DescribeDBClusters(context.Context, *rds.DescribeDBClustersInput, ...func(*rds.Options)) (*rds.DescribeDBClustersOutput, error)
|
||||
DescribeDBInstances(context.Context, *rds.DescribeDBInstancesInput, ...func(*rds.Options)) (*rds.DescribeDBInstancesOutput, error)
|
||||
}
|
||||
|
||||
// RDSDiscovery periodically performs RDS-SD requests. It implements
|
||||
// the Discoverer interface.
|
||||
type RDSDiscovery struct {
|
||||
*refresh.Discovery
|
||||
logger *slog.Logger
|
||||
cfg *RDSSDConfig
|
||||
rds rdsClient
|
||||
}
|
||||
|
||||
// NewRDSDiscovery returns a new RDSDiscovery which periodically refreshes its targets.
|
||||
func NewRDSDiscovery(conf *RDSSDConfig, opts discovery.DiscovererOptions) (*RDSDiscovery, error) {
|
||||
m, ok := opts.Metrics.(*rdsMetrics)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid discovery metrics type")
|
||||
}
|
||||
|
||||
if opts.Logger == nil {
|
||||
opts.Logger = promslog.NewNopLogger()
|
||||
}
|
||||
d := &RDSDiscovery{
|
||||
logger: opts.Logger,
|
||||
cfg: conf,
|
||||
}
|
||||
d.Discovery = refresh.NewDiscovery(
|
||||
refresh.Options{
|
||||
Logger: opts.Logger,
|
||||
Mech: "rds",
|
||||
Interval: time.Duration(d.cfg.RefreshInterval),
|
||||
RefreshF: d.refresh,
|
||||
MetricsInstantiator: m.refreshMetrics,
|
||||
},
|
||||
)
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *RDSDiscovery) initRdsClient(ctx context.Context) error {
|
||||
if d.rds != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.cfg.Region == "" {
|
||||
return errors.New("region must be set for RDS service discovery")
|
||||
}
|
||||
|
||||
// Build the HTTP client from the provided HTTPClientConfig.
|
||||
client, err := config.NewClientFromConfig(d.cfg.HTTPClientConfig, "rds_sd")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build the AWS config with the provided region.
|
||||
var configOptions []func(*awsConfig.LoadOptions) error
|
||||
configOptions = append(configOptions, awsConfig.WithRegion(d.cfg.Region))
|
||||
configOptions = append(configOptions, awsConfig.WithHTTPClient(client))
|
||||
|
||||
// Only set static credentials if both access key and secret key are provided
|
||||
// Otherwise, let AWS SDK use its default credential chain
|
||||
if d.cfg.AccessKey != "" && d.cfg.SecretKey != "" {
|
||||
credProvider := credentials.NewStaticCredentialsProvider(d.cfg.AccessKey, string(d.cfg.SecretKey), "")
|
||||
configOptions = append(configOptions, awsConfig.WithCredentialsProvider(credProvider))
|
||||
}
|
||||
|
||||
if d.cfg.Profile != "" {
|
||||
configOptions = append(configOptions, awsConfig.WithSharedConfigProfile(d.cfg.Profile))
|
||||
}
|
||||
|
||||
cfg, err := awsConfig.LoadDefaultConfig(ctx, configOptions...)
|
||||
if err != nil {
|
||||
d.logger.Error("Failed to create AWS config", "error", err)
|
||||
return fmt.Errorf("could not create aws config: %w", err)
|
||||
}
|
||||
|
||||
// If the role ARN is set, assume the role to get credentials and set the credentials provider in the config.
|
||||
if d.cfg.RoleARN != "" {
|
||||
assumeProvider := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), d.cfg.RoleARN)
|
||||
cfg.Credentials = aws.NewCredentialsCache(assumeProvider)
|
||||
}
|
||||
|
||||
d.rds = rds.NewFromConfig(cfg, func(options *rds.Options) {
|
||||
if d.cfg.Endpoint != "" {
|
||||
options.BaseEndpoint = &d.cfg.Endpoint
|
||||
}
|
||||
options.HTTPClient = client
|
||||
})
|
||||
|
||||
// Test credentials by making a simple API call
|
||||
testCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err = d.rds.DescribeDBClusters(testCtx, &rds.DescribeDBClustersInput{})
|
||||
if err != nil {
|
||||
d.logger.Error("Failed to test RDS credentials", "error", err)
|
||||
return fmt.Errorf("RDS credential test failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RDSDiscovery) describeAllDBClusters(ctx context.Context) (map[string]types.DBCluster, error) {
|
||||
dbClustersByARN := make(map[string]types.DBCluster)
|
||||
var nextToken *string
|
||||
|
||||
for {
|
||||
output, err := d.rds.DescribeDBClusters(ctx, &rds.DescribeDBClustersInput{
|
||||
Marker: nextToken,
|
||||
MaxRecords: aws.Int32(100),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to describe DB clusters: %w", err)
|
||||
}
|
||||
for _, dbCluster := range output.DBClusters {
|
||||
if dbCluster.DBClusterArn != nil {
|
||||
dbClustersByARN[*dbCluster.DBClusterArn] = dbCluster
|
||||
}
|
||||
}
|
||||
if output.Marker == nil {
|
||||
break
|
||||
}
|
||||
nextToken = output.Marker
|
||||
}
|
||||
|
||||
return dbClustersByARN, nil
|
||||
}
|
||||
|
||||
func (d *RDSDiscovery) describeDBClusters(ctx context.Context, dbClusterARNS []string) (map[string]types.DBCluster, error) {
|
||||
mu := &sync.Mutex{}
|
||||
errg, ectx := errgroup.WithContext(ctx)
|
||||
errg.SetLimit(d.cfg.RequestConcurrency)
|
||||
dbClustersByARN := make(map[string]types.DBCluster)
|
||||
var nextToken *string
|
||||
|
||||
for _, arn := range dbClusterARNS {
|
||||
errg.Go(func() error {
|
||||
for {
|
||||
output, err := d.rds.DescribeDBClusters(ectx, &rds.DescribeDBClustersInput{
|
||||
DBClusterIdentifier: aws.String(arn),
|
||||
Marker: nextToken,
|
||||
MaxRecords: aws.Int32(100),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to describe DB cluster %s: %w", arn, err)
|
||||
}
|
||||
if len(output.DBClusters) == 0 {
|
||||
return fmt.Errorf("no DB cluster found for ARN %s", arn)
|
||||
}
|
||||
|
||||
for _, dbCluster := range output.DBClusters {
|
||||
mu.Lock()
|
||||
dbClustersByARN[arn] = dbCluster
|
||||
mu.Unlock()
|
||||
}
|
||||
if output.Marker == nil {
|
||||
break
|
||||
}
|
||||
nextToken = output.Marker
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return dbClustersByARN, errg.Wait()
|
||||
}
|
||||
|
||||
func (d *RDSDiscovery) describeDBInstances(ctx context.Context, dbClusterARN string) ([]types.DBInstance, error) {
|
||||
mu := &sync.Mutex{}
|
||||
errg, ectx := errgroup.WithContext(ctx)
|
||||
errg.SetLimit(d.cfg.RequestConcurrency)
|
||||
dbInstances := []types.DBInstance{}
|
||||
var nextToken *string
|
||||
for {
|
||||
output, err := d.rds.DescribeDBInstances(ectx, &rds.DescribeDBInstancesInput{
|
||||
Filters: []types.Filter{
|
||||
{
|
||||
Name: aws.String("db-cluster-id"),
|
||||
Values: []string{dbClusterARN},
|
||||
},
|
||||
},
|
||||
Marker: nextToken,
|
||||
MaxRecords: aws.Int32(100),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to describe DB instances for cluster ARN %s: %w", dbClusterARN, err)
|
||||
}
|
||||
if len(output.DBInstances) == 0 {
|
||||
return nil, fmt.Errorf("no DB instances found for cluster ARN %s", dbClusterARN)
|
||||
}
|
||||
|
||||
for _, dbInstance := range output.DBInstances {
|
||||
mu.Lock()
|
||||
dbInstances = append(dbInstances, dbInstance)
|
||||
mu.Unlock()
|
||||
}
|
||||
if output.Marker == nil {
|
||||
break
|
||||
}
|
||||
nextToken = output.Marker
|
||||
}
|
||||
return dbInstances, errg.Wait()
|
||||
}
|
||||
|
||||
func (d *RDSDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
||||
err := d.initRdsClient(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tg := &targetgroup.Group{
|
||||
Source: d.cfg.Region,
|
||||
}
|
||||
|
||||
var clusters map[string]types.DBCluster
|
||||
if len(d.cfg.Clusters) == 0 {
|
||||
clusters, err = d.describeAllDBClusters(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing all DB clusters: %w", err)
|
||||
}
|
||||
} else {
|
||||
clusters, err = d.describeDBClusters(ctx, d.cfg.Clusters)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing DB clusters: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
for _, cluster := range clusters {
|
||||
wg.Add(1)
|
||||
|
||||
instances, err := d.describeDBInstances(ctx, *cluster.DBClusterArn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing DB instances: %w", err)
|
||||
}
|
||||
|
||||
go func(cluster types.DBCluster, instances []types.DBInstance) {
|
||||
defer wg.Done()
|
||||
|
||||
// Build a map of instance identifiers to their IsClusterWriter status
|
||||
writerMap := make(map[string]bool)
|
||||
for _, member := range cluster.DBClusterMembers {
|
||||
if member.DBInstanceIdentifier != nil && member.IsClusterWriter != nil {
|
||||
writerMap[*member.DBInstanceIdentifier] = *member.IsClusterWriter
|
||||
}
|
||||
}
|
||||
|
||||
for _, instance := range instances {
|
||||
labels := model.LabelSet{}
|
||||
|
||||
// Cluster labels
|
||||
if cluster.DBClusterArn != nil {
|
||||
labels[rdsLabelClusterDBClusterArn] = model.LabelValue(*cluster.DBClusterArn)
|
||||
}
|
||||
if cluster.DBClusterIdentifier != nil {
|
||||
labels[rdsLabelClusterDBClusterIdentifier] = model.LabelValue(*cluster.DBClusterIdentifier)
|
||||
}
|
||||
if cluster.ActivityStreamKinesisStreamName != nil {
|
||||
labels[rdsLabelClusterActivityStreamKinesisStreamName] = model.LabelValue(*cluster.ActivityStreamKinesisStreamName)
|
||||
}
|
||||
if cluster.ActivityStreamKmsKeyId != nil {
|
||||
labels[rdsLabelClusterActivityStreamKMSKeyID] = model.LabelValue(*cluster.ActivityStreamKmsKeyId)
|
||||
}
|
||||
if cluster.ActivityStreamMode != "" {
|
||||
labels[rdsLabelClusterActivityStreamMode] = model.LabelValue(cluster.ActivityStreamMode)
|
||||
}
|
||||
if cluster.ActivityStreamStatus != "" {
|
||||
labels[rdsLabelClusterActivityStreamStatus] = model.LabelValue(cluster.ActivityStreamStatus)
|
||||
}
|
||||
if cluster.AllocatedStorage != nil {
|
||||
labels[rdsLabelClusterAllocatedStorage] = model.LabelValue(strconv.Itoa(int(*cluster.AllocatedStorage)))
|
||||
}
|
||||
if cluster.AutoMinorVersionUpgrade != nil {
|
||||
labels[rdsLabelClusterAutoMinorVersionUpgrade] = model.LabelValue(strconv.FormatBool(*cluster.AutoMinorVersionUpgrade))
|
||||
}
|
||||
if cluster.AutomaticRestartTime != nil {
|
||||
labels[rdsLabelClusterAutomaticRestartTime] = model.LabelValue(cluster.AutomaticRestartTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.AwsBackupRecoveryPointArn != nil {
|
||||
labels[rdsLabelClusterAwsBackupRecoveryPointArn] = model.LabelValue(*cluster.AwsBackupRecoveryPointArn)
|
||||
}
|
||||
if cluster.BacktrackConsumedChangeRecords != nil {
|
||||
labels[rdsLabelClusterBacktrackConsumedChangeRecords] = model.LabelValue(strconv.FormatInt(*cluster.BacktrackConsumedChangeRecords, 10))
|
||||
}
|
||||
if cluster.BacktrackWindow != nil {
|
||||
labels[rdsLabelClusterBacktrackWindow] = model.LabelValue(strconv.FormatInt(*cluster.BacktrackWindow, 10))
|
||||
}
|
||||
if cluster.BackupRetentionPeriod != nil {
|
||||
labels[rdsLabelClusterBackupRetentionPeriod] = model.LabelValue(strconv.Itoa(int(*cluster.BackupRetentionPeriod)))
|
||||
}
|
||||
if cluster.Capacity != nil {
|
||||
labels[rdsLabelClusterCapacity] = model.LabelValue(strconv.Itoa(int(*cluster.Capacity)))
|
||||
}
|
||||
if cluster.CharacterSetName != nil {
|
||||
labels[rdsLabelClusterCharacterSetName] = model.LabelValue(*cluster.CharacterSetName)
|
||||
}
|
||||
if cluster.CloneGroupId != nil {
|
||||
labels[rdsLabelClusterCloneGroupID] = model.LabelValue(*cluster.CloneGroupId)
|
||||
}
|
||||
if cluster.ClusterCreateTime != nil {
|
||||
labels[rdsLabelClusterClusterCreateTime] = model.LabelValue(cluster.ClusterCreateTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.ClusterScalabilityType != "" {
|
||||
labels[rdsLabelClusterClusterScalabilityType] = model.LabelValue(cluster.ClusterScalabilityType)
|
||||
}
|
||||
if cluster.CopyTagsToSnapshot != nil {
|
||||
labels[rdsLabelClusterCopyTagsToSnapshot] = model.LabelValue(strconv.FormatBool(*cluster.CopyTagsToSnapshot))
|
||||
}
|
||||
if cluster.CrossAccountClone != nil {
|
||||
labels[rdsLabelClusterCrossAccountClone] = model.LabelValue(strconv.FormatBool(*cluster.CrossAccountClone))
|
||||
}
|
||||
if cluster.DBClusterInstanceClass != nil {
|
||||
labels[rdsLabelClusterDBClusterInstanceClass] = model.LabelValue(*cluster.DBClusterInstanceClass)
|
||||
}
|
||||
if cluster.DBClusterParameterGroup != nil {
|
||||
labels[rdsLabelClusterDBClusterParameterGroup] = model.LabelValue(*cluster.DBClusterParameterGroup)
|
||||
}
|
||||
if cluster.DBSubnetGroup != nil {
|
||||
labels[rdsLabelClusterDBSubnetGroup] = model.LabelValue(*cluster.DBSubnetGroup)
|
||||
}
|
||||
if cluster.DBSystemId != nil {
|
||||
labels[rdsLabelClusterDBSystemID] = model.LabelValue(*cluster.DBSystemId)
|
||||
}
|
||||
if cluster.DatabaseInsightsMode != "" {
|
||||
labels[rdsLabelClusterDatabaseInsightsMode] = model.LabelValue(cluster.DatabaseInsightsMode)
|
||||
}
|
||||
if cluster.DatabaseName != nil {
|
||||
labels[rdsLabelClusterDatabaseName] = model.LabelValue(*cluster.DatabaseName)
|
||||
}
|
||||
if cluster.DbClusterResourceId != nil {
|
||||
labels[rdsLabelClusterDBClusterResourceID] = model.LabelValue(*cluster.DbClusterResourceId)
|
||||
}
|
||||
if cluster.DeletionProtection != nil {
|
||||
labels[rdsLabelClusterDeletionProtection] = model.LabelValue(strconv.FormatBool(*cluster.DeletionProtection))
|
||||
}
|
||||
if cluster.EarliestBacktrackTime != nil {
|
||||
labels[rdsLabelClusterEarliestBacktrackTime] = model.LabelValue(cluster.EarliestBacktrackTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.EarliestRestorableTime != nil {
|
||||
labels[rdsLabelClusterEarliestRestorableTime] = model.LabelValue(cluster.EarliestRestorableTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.Endpoint != nil {
|
||||
labels[rdsLabelClusterEndpoint] = model.LabelValue(*cluster.Endpoint)
|
||||
}
|
||||
if cluster.Engine != nil {
|
||||
labels[rdsLabelClusterEngine] = model.LabelValue(*cluster.Engine)
|
||||
}
|
||||
if cluster.EngineLifecycleSupport != nil {
|
||||
labels[rdsLabelClusterEngineLifecycleSupport] = model.LabelValue(*cluster.EngineLifecycleSupport)
|
||||
}
|
||||
if cluster.EngineMode != nil {
|
||||
labels[rdsLabelClusterEngineMode] = model.LabelValue(*cluster.EngineMode)
|
||||
}
|
||||
if cluster.EngineVersion != nil {
|
||||
labels[rdsLabelClusterEngineVersion] = model.LabelValue(*cluster.EngineVersion)
|
||||
}
|
||||
if cluster.GlobalClusterIdentifier != nil {
|
||||
labels[rdsLabelClusterGlobalClusterIdentifier] = model.LabelValue(*cluster.GlobalClusterIdentifier)
|
||||
}
|
||||
if cluster.GlobalWriteForwardingRequested != nil {
|
||||
labels[rdsLabelClusterGlobalWriteForwardingRequested] = model.LabelValue(strconv.FormatBool(*cluster.GlobalWriteForwardingRequested))
|
||||
}
|
||||
if cluster.GlobalWriteForwardingStatus != "" {
|
||||
labels[rdsLabelClusterGlobalWriteForwardingStatus] = model.LabelValue(cluster.GlobalWriteForwardingStatus)
|
||||
}
|
||||
if cluster.HostedZoneId != nil {
|
||||
labels[rdsLabelClusterHostedZoneID] = model.LabelValue(*cluster.HostedZoneId)
|
||||
}
|
||||
if cluster.HttpEndpointEnabled != nil {
|
||||
labels[rdsLabelClusterHTTPEndpointEnabled] = model.LabelValue(strconv.FormatBool(*cluster.HttpEndpointEnabled))
|
||||
}
|
||||
if cluster.IAMDatabaseAuthenticationEnabled != nil {
|
||||
labels[rdsLabelClusterIAMDatabaseAuthenticationEnabled] = model.LabelValue(strconv.FormatBool(*cluster.IAMDatabaseAuthenticationEnabled))
|
||||
}
|
||||
if cluster.IOOptimizedNextAllowedModificationTime != nil {
|
||||
labels[rdsLabelClusterIOOptimizedNextAllowedModificationTime] = model.LabelValue(cluster.IOOptimizedNextAllowedModificationTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.Iops != nil {
|
||||
labels[rdsLabelClusterIops] = model.LabelValue(strconv.Itoa(int(*cluster.Iops)))
|
||||
}
|
||||
if cluster.KmsKeyId != nil {
|
||||
labels[rdsLabelClusterKMSKeyID] = model.LabelValue(*cluster.KmsKeyId)
|
||||
}
|
||||
if cluster.LatestRestorableTime != nil {
|
||||
labels[rdsLabelClusterLatestRestorableTime] = model.LabelValue(cluster.LatestRestorableTime.Format(time.RFC3339))
|
||||
}
|
||||
if cluster.LocalWriteForwardingStatus != "" {
|
||||
labels[rdsLabelClusterLocalWriteForwardingStatus] = model.LabelValue(cluster.LocalWriteForwardingStatus)
|
||||
}
|
||||
if cluster.MasterUsername != nil {
|
||||
labels[rdsLabelClusterMasterUsername] = model.LabelValue(*cluster.MasterUsername)
|
||||
}
|
||||
if cluster.MonitoringInterval != nil {
|
||||
labels[rdsLabelClusterMonitoringInterval] = model.LabelValue(strconv.Itoa(int(*cluster.MonitoringInterval)))
|
||||
}
|
||||
if cluster.MonitoringRoleArn != nil {
|
||||
labels[rdsLabelClusterMonitoringRoleArn] = model.LabelValue(*cluster.MonitoringRoleArn)
|
||||
}
|
||||
if cluster.MultiAZ != nil {
|
||||
labels[rdsLabelClusterMultiAZ] = model.LabelValue(strconv.FormatBool(*cluster.MultiAZ))
|
||||
}
|
||||
if cluster.NetworkType != nil {
|
||||
labels[rdsLabelClusterNetworkType] = model.LabelValue(*cluster.NetworkType)
|
||||
}
|
||||
if cluster.PercentProgress != nil {
|
||||
labels[rdsLabelClusterPercentProgress] = model.LabelValue(*cluster.PercentProgress)
|
||||
}
|
||||
if cluster.PerformanceInsightsEnabled != nil {
|
||||
labels[rdsLabelClusterPerformanceInsightsEnabled] = model.LabelValue(strconv.FormatBool(*cluster.PerformanceInsightsEnabled))
|
||||
}
|
||||
if cluster.PerformanceInsightsKMSKeyId != nil {
|
||||
labels[rdsLabelClusterPerformanceInsightsKMSKeyID] = model.LabelValue(*cluster.PerformanceInsightsKMSKeyId)
|
||||
}
|
||||
if cluster.PerformanceInsightsRetentionPeriod != nil {
|
||||
labels[rdsLabelClusterPerformanceInsightsRetentionPeriod] = model.LabelValue(strconv.Itoa(int(*cluster.PerformanceInsightsRetentionPeriod)))
|
||||
}
|
||||
if cluster.Port != nil {
|
||||
labels[rdsLabelClusterPort] = model.LabelValue(strconv.Itoa(int(*cluster.Port)))
|
||||
}
|
||||
if cluster.PreferredBackupWindow != nil {
|
||||
labels[rdsLabelClusterPreferredBackupWindow] = model.LabelValue(*cluster.PreferredBackupWindow)
|
||||
}
|
||||
if cluster.PreferredMaintenanceWindow != nil {
|
||||
labels[rdsLabelClusterPreferredMaintenanceWindow] = model.LabelValue(*cluster.PreferredMaintenanceWindow)
|
||||
}
|
||||
if cluster.PubliclyAccessible != nil {
|
||||
labels[rdsLabelClusterPubliclyAccessible] = model.LabelValue(strconv.FormatBool(*cluster.PubliclyAccessible))
|
||||
}
|
||||
if cluster.ReaderEndpoint != nil {
|
||||
labels[rdsLabelClusterReaderEndpoint] = model.LabelValue(*cluster.ReaderEndpoint)
|
||||
}
|
||||
if cluster.ReplicationSourceIdentifier != nil {
|
||||
labels[rdsLabelClusterReplicationSourceIdentifier] = model.LabelValue(*cluster.ReplicationSourceIdentifier)
|
||||
}
|
||||
if cluster.ServerlessV2PlatformVersion != nil {
|
||||
labels[rdsLabelClusterServerlessV2PlatformVersion] = model.LabelValue(*cluster.ServerlessV2PlatformVersion)
|
||||
}
|
||||
if cluster.Status != nil {
|
||||
labels[rdsLabelClusterStatus] = model.LabelValue(*cluster.Status)
|
||||
}
|
||||
if cluster.StorageEncrypted != nil {
|
||||
labels[rdsLabelClusterStorageEncrypted] = model.LabelValue(strconv.FormatBool(*cluster.StorageEncrypted))
|
||||
}
|
||||
if cluster.StorageEncryptionType != "" {
|
||||
labels[rdsLabelClusterStorageEncryptionType] = model.LabelValue(cluster.StorageEncryptionType)
|
||||
}
|
||||
if cluster.StorageThroughput != nil {
|
||||
labels[rdsLabelClusterStorageThroughput] = model.LabelValue(strconv.Itoa(int(*cluster.StorageThroughput)))
|
||||
}
|
||||
if cluster.StorageType != nil {
|
||||
labels[rdsLabelClusterStorageType] = model.LabelValue(*cluster.StorageType)
|
||||
}
|
||||
if cluster.UpgradeRolloutOrder != "" {
|
||||
labels[rdsLabelClusterUpgradeRolloutOrder] = model.LabelValue(cluster.UpgradeRolloutOrder)
|
||||
}
|
||||
|
||||
// Cluster tags
|
||||
for _, tag := range cluster.TagList {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
labels[model.LabelName(rdsLabelClusterTag+strutil.SanitizeLabelName(*tag.Key))] = model.LabelValue(*tag.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Instance labels
|
||||
if instance.DBInstanceArn != nil {
|
||||
labels[rdsLabelInstanceDBInstanceArn] = model.LabelValue(*instance.DBInstanceArn)
|
||||
}
|
||||
if instance.DBInstanceIdentifier != nil {
|
||||
labels[rdsLabelInstanceDBInstanceIdentifier] = model.LabelValue(*instance.DBInstanceIdentifier)
|
||||
// Set IsClusterWriter based on cluster membership information
|
||||
if isWriter, found := writerMap[*instance.DBInstanceIdentifier]; found {
|
||||
labels[rdsLabelInstanceIsClusterWriter] = model.LabelValue(strconv.FormatBool(isWriter))
|
||||
}
|
||||
}
|
||||
if instance.ActivityStreamEngineNativeAuditFieldsIncluded != nil {
|
||||
labels[rdsLabelInstanceActivityStreamEngineNativeAuditFieldsIncluded] = model.LabelValue(strconv.FormatBool(*instance.ActivityStreamEngineNativeAuditFieldsIncluded))
|
||||
}
|
||||
if instance.ActivityStreamKinesisStreamName != nil {
|
||||
labels[rdsLabelInstanceActivityStreamKinesisStreamName] = model.LabelValue(*instance.ActivityStreamKinesisStreamName)
|
||||
}
|
||||
if instance.ActivityStreamKmsKeyId != nil {
|
||||
labels[rdsLabelInstanceActivityStreamKmsKeyID] = model.LabelValue(*instance.ActivityStreamKmsKeyId)
|
||||
}
|
||||
if instance.ActivityStreamMode != "" {
|
||||
labels[rdsLabelInstanceActivityStreamMode] = model.LabelValue(instance.ActivityStreamMode)
|
||||
}
|
||||
if instance.ActivityStreamPolicyStatus != "" {
|
||||
labels[rdsLabelInstanceActivityStreamPolicyStatus] = model.LabelValue(instance.ActivityStreamPolicyStatus)
|
||||
}
|
||||
if instance.ActivityStreamStatus != "" {
|
||||
labels[rdsLabelInstanceActivityStreamStatus] = model.LabelValue(instance.ActivityStreamStatus)
|
||||
}
|
||||
if instance.AllocatedStorage != nil {
|
||||
labels[rdsLabelInstanceAllocatedStorage] = model.LabelValue(strconv.Itoa(int(*instance.AllocatedStorage)))
|
||||
}
|
||||
if instance.AutoMinorVersionUpgrade != nil {
|
||||
labels[rdsLabelInstanceAutoMinorVersionUpgrade] = model.LabelValue(strconv.FormatBool(*instance.AutoMinorVersionUpgrade))
|
||||
}
|
||||
if instance.AutomaticRestartTime != nil {
|
||||
labels[rdsLabelInstanceAutomaticRestartTime] = model.LabelValue(instance.AutomaticRestartTime.Format(time.RFC3339))
|
||||
}
|
||||
if instance.AutomationMode != "" {
|
||||
labels[rdsLabelInstanceAutomationMode] = model.LabelValue(instance.AutomationMode)
|
||||
}
|
||||
if instance.AvailabilityZone != nil {
|
||||
labels[rdsLabelInstanceAvailabilityZone] = model.LabelValue(*instance.AvailabilityZone)
|
||||
}
|
||||
if instance.AwsBackupRecoveryPointArn != nil {
|
||||
labels[rdsLabelInstanceAwsBackupRecoveryPointArn] = model.LabelValue(*instance.AwsBackupRecoveryPointArn)
|
||||
}
|
||||
if instance.BackupRetentionPeriod != nil {
|
||||
labels[rdsLabelInstanceBackupRetentionPeriod] = model.LabelValue(strconv.Itoa(int(*instance.BackupRetentionPeriod)))
|
||||
}
|
||||
if instance.BackupTarget != nil {
|
||||
labels[rdsLabelInstanceBackupTarget] = model.LabelValue(*instance.BackupTarget)
|
||||
}
|
||||
if instance.CACertificateIdentifier != nil {
|
||||
labels[rdsLabelInstanceCACertificateIdentifier] = model.LabelValue(*instance.CACertificateIdentifier)
|
||||
}
|
||||
if instance.CharacterSetName != nil {
|
||||
labels[rdsLabelInstanceCharacterSetName] = model.LabelValue(*instance.CharacterSetName)
|
||||
}
|
||||
if instance.CopyTagsToSnapshot != nil {
|
||||
labels[rdsLabelInstanceCopyTagsToSnapshot] = model.LabelValue(strconv.FormatBool(*instance.CopyTagsToSnapshot))
|
||||
}
|
||||
if instance.CustomIamInstanceProfile != nil {
|
||||
labels[rdsLabelInstanceCustomIamInstanceProfile] = model.LabelValue(*instance.CustomIamInstanceProfile)
|
||||
}
|
||||
if instance.CustomerOwnedIpEnabled != nil {
|
||||
labels[rdsLabelInstanceCustomerOwnedIPEnabled] = model.LabelValue(strconv.FormatBool(*instance.CustomerOwnedIpEnabled))
|
||||
}
|
||||
if instance.DBClusterIdentifier != nil {
|
||||
labels[rdsLabelInstanceDBClusterIdentifier] = model.LabelValue(*instance.DBClusterIdentifier)
|
||||
}
|
||||
if instance.DBInstanceClass != nil {
|
||||
labels[rdsLabelInstanceDBInstanceClass] = model.LabelValue(*instance.DBInstanceClass)
|
||||
}
|
||||
if instance.DBInstanceStatus != nil {
|
||||
labels[rdsLabelInstanceDBInstanceStatus] = model.LabelValue(*instance.DBInstanceStatus)
|
||||
}
|
||||
if instance.DBName != nil {
|
||||
labels[rdsLabelInstanceDBName] = model.LabelValue(*instance.DBName)
|
||||
}
|
||||
if instance.DbInstancePort != nil {
|
||||
labels[rdsLabelInstanceDBInstancePort] = model.LabelValue(strconv.Itoa(int(*instance.DbInstancePort)))
|
||||
}
|
||||
if instance.DbiResourceId != nil {
|
||||
labels[rdsLabelInstanceDBResourceID] = model.LabelValue(*instance.DbiResourceId)
|
||||
}
|
||||
if instance.DedicatedLogVolume != nil {
|
||||
labels[rdsLabelInstanceDedicatedLogVolume] = model.LabelValue(strconv.FormatBool(*instance.DedicatedLogVolume))
|
||||
}
|
||||
if instance.DeletionProtection != nil {
|
||||
labels[rdsLabelInstanceDeletionProtection] = model.LabelValue(strconv.FormatBool(*instance.DeletionProtection))
|
||||
}
|
||||
if instance.Endpoint != nil {
|
||||
if instance.Endpoint.Address != nil {
|
||||
labels[rdsLabelInstanceEndpointAddress] = model.LabelValue(*instance.Endpoint.Address)
|
||||
}
|
||||
if instance.Endpoint.HostedZoneId != nil {
|
||||
labels[rdsLabelInstanceEndpointHostedZoneID] = model.LabelValue(*instance.Endpoint.HostedZoneId)
|
||||
}
|
||||
if instance.Endpoint.Port != nil {
|
||||
labels[rdsLabelInstanceEndpointPort] = model.LabelValue(strconv.Itoa(int(*instance.Endpoint.Port)))
|
||||
}
|
||||
}
|
||||
if instance.Engine != nil {
|
||||
labels[rdsLabelInstanceEngine] = model.LabelValue(*instance.Engine)
|
||||
}
|
||||
if instance.EngineLifecycleSupport != nil {
|
||||
labels[rdsLabelInstanceEngineLifecycleSupport] = model.LabelValue(*instance.EngineLifecycleSupport)
|
||||
}
|
||||
if instance.EngineVersion != nil {
|
||||
labels[rdsLabelInstanceEngineVersion] = model.LabelValue(*instance.EngineVersion)
|
||||
}
|
||||
if instance.EnhancedMonitoringResourceArn != nil {
|
||||
labels[rdsLabelInstanceEnhancedMonitoringResourceArn] = model.LabelValue(*instance.EnhancedMonitoringResourceArn)
|
||||
}
|
||||
if instance.IAMDatabaseAuthenticationEnabled != nil {
|
||||
labels[rdsLabelInstanceIAMDatabaseAuthenticationEnabled] = model.LabelValue(strconv.FormatBool(*instance.IAMDatabaseAuthenticationEnabled))
|
||||
}
|
||||
if instance.InstanceCreateTime != nil {
|
||||
labels[rdsLabelInstanceInstanceCreateTime] = model.LabelValue(instance.InstanceCreateTime.Format(time.RFC3339))
|
||||
}
|
||||
if instance.Iops != nil {
|
||||
labels[rdsLabelInstanceIops] = model.LabelValue(strconv.Itoa(int(*instance.Iops)))
|
||||
}
|
||||
if instance.IsStorageConfigUpgradeAvailable != nil {
|
||||
labels[rdsLabelInstanceIsStorageConfigUpgradeAvailable] = model.LabelValue(strconv.FormatBool(*instance.IsStorageConfigUpgradeAvailable))
|
||||
}
|
||||
if instance.KmsKeyId != nil {
|
||||
labels[rdsLabelInstanceKMSKeyID] = model.LabelValue(*instance.KmsKeyId)
|
||||
}
|
||||
if instance.LatestRestorableTime != nil {
|
||||
labels[rdsLabelInstanceLatestRestorableTime] = model.LabelValue(instance.LatestRestorableTime.Format(time.RFC3339))
|
||||
}
|
||||
if instance.LicenseModel != nil {
|
||||
labels[rdsLabelInstanceLicenseModel] = model.LabelValue(*instance.LicenseModel)
|
||||
}
|
||||
if instance.ListenerEndpoint != nil {
|
||||
if instance.ListenerEndpoint.Address != nil {
|
||||
labels[rdsLabelInstanceListenerEndpointAddress] = model.LabelValue(*instance.ListenerEndpoint.Address)
|
||||
}
|
||||
if instance.ListenerEndpoint.HostedZoneId != nil {
|
||||
labels[rdsLabelInstanceListenerEndpointHostedZoneID] = model.LabelValue(*instance.ListenerEndpoint.HostedZoneId)
|
||||
}
|
||||
if instance.ListenerEndpoint.Port != nil {
|
||||
labels[rdsLabelInstanceListenerEndpointPort] = model.LabelValue(strconv.Itoa(int(*instance.ListenerEndpoint.Port)))
|
||||
}
|
||||
}
|
||||
if instance.MasterUsername != nil {
|
||||
labels[rdsLabelInstanceMasterUsername] = model.LabelValue(*instance.MasterUsername)
|
||||
}
|
||||
if instance.MaxAllocatedStorage != nil {
|
||||
labels[rdsLabelInstanceMaxAllocatedStorage] = model.LabelValue(strconv.Itoa(int(*instance.MaxAllocatedStorage)))
|
||||
}
|
||||
if instance.MonitoringInterval != nil {
|
||||
labels[rdsLabelInstanceMonitoringInterval] = model.LabelValue(strconv.Itoa(int(*instance.MonitoringInterval)))
|
||||
}
|
||||
if instance.MonitoringRoleArn != nil {
|
||||
labels[rdsLabelInstanceMonitoringRoleArn] = model.LabelValue(*instance.MonitoringRoleArn)
|
||||
}
|
||||
if instance.MultiAZ != nil {
|
||||
labels[rdsLabelInstanceMultiAZ] = model.LabelValue(strconv.FormatBool(*instance.MultiAZ))
|
||||
}
|
||||
if instance.MultiTenant != nil {
|
||||
labels[rdsLabelInstanceMultiTenant] = model.LabelValue(strconv.FormatBool(*instance.MultiTenant))
|
||||
}
|
||||
if instance.NcharCharacterSetName != nil {
|
||||
labels[rdsLabelInstanceNcharCharacterSetName] = model.LabelValue(*instance.NcharCharacterSetName)
|
||||
}
|
||||
if instance.NetworkType != nil {
|
||||
labels[rdsLabelInstanceNetworkType] = model.LabelValue(*instance.NetworkType)
|
||||
}
|
||||
if instance.PercentProgress != nil {
|
||||
labels[rdsLabelInstancePercentProgress] = model.LabelValue(*instance.PercentProgress)
|
||||
}
|
||||
if instance.PerformanceInsightsEnabled != nil {
|
||||
labels[rdsLabelInstancePerformanceInsightsEnabled] = model.LabelValue(strconv.FormatBool(*instance.PerformanceInsightsEnabled))
|
||||
}
|
||||
if instance.PerformanceInsightsKMSKeyId != nil {
|
||||
labels[rdsLabelInstancePerformanceInsightsKMSKeyID] = model.LabelValue(*instance.PerformanceInsightsKMSKeyId)
|
||||
}
|
||||
if instance.PerformanceInsightsRetentionPeriod != nil {
|
||||
labels[rdsLabelInstancePerformanceInsightsRetentionPeriod] = model.LabelValue(strconv.Itoa(int(*instance.PerformanceInsightsRetentionPeriod)))
|
||||
}
|
||||
if instance.PreferredBackupWindow != nil {
|
||||
labels[rdsLabelInstancePreferredBackupWindow] = model.LabelValue(*instance.PreferredBackupWindow)
|
||||
}
|
||||
if instance.PreferredMaintenanceWindow != nil {
|
||||
labels[rdsLabelInstancePreferredMaintenanceWindow] = model.LabelValue(*instance.PreferredMaintenanceWindow)
|
||||
}
|
||||
if instance.PromotionTier != nil {
|
||||
labels[rdsLabelInstancePromotionTier] = model.LabelValue(strconv.Itoa(int(*instance.PromotionTier)))
|
||||
}
|
||||
if instance.PubliclyAccessible != nil {
|
||||
labels[rdsLabelInstancePubliclyAccessible] = model.LabelValue(strconv.FormatBool(*instance.PubliclyAccessible))
|
||||
}
|
||||
if instance.ReadReplicaSourceDBClusterIdentifier != nil {
|
||||
labels[rdsLabelInstanceReadReplicaSourceDBClusterIdentifier] = model.LabelValue(*instance.ReadReplicaSourceDBClusterIdentifier)
|
||||
}
|
||||
if instance.ReadReplicaSourceDBInstanceIdentifier != nil {
|
||||
labels[rdsLabelInstanceReadReplicaSourceDBInstanceIdentifier] = model.LabelValue(*instance.ReadReplicaSourceDBInstanceIdentifier)
|
||||
}
|
||||
if instance.ReplicaMode != "" {
|
||||
labels[rdsLabelInstanceReplicaMode] = model.LabelValue(instance.ReplicaMode)
|
||||
}
|
||||
if instance.ResumeFullAutomationModeTime != nil {
|
||||
labels[rdsLabelInstanceResumeFullAutomationModeTime] = model.LabelValue(instance.ResumeFullAutomationModeTime.Format(time.RFC3339))
|
||||
}
|
||||
if instance.SecondaryAvailabilityZone != nil {
|
||||
labels[rdsLabelInstanceSecondaryAvailabilityZone] = model.LabelValue(*instance.SecondaryAvailabilityZone)
|
||||
}
|
||||
if instance.StorageEncrypted != nil {
|
||||
labels[rdsLabelInstanceStorageEncrypted] = model.LabelValue(strconv.FormatBool(*instance.StorageEncrypted))
|
||||
}
|
||||
if instance.StorageEncryptionType != "" {
|
||||
labels[rdsLabelInstanceStorageEncryptionType] = model.LabelValue(instance.StorageEncryptionType)
|
||||
}
|
||||
if instance.StorageThroughput != nil {
|
||||
labels[rdsLabelInstanceStorageThroughput] = model.LabelValue(strconv.Itoa(int(*instance.StorageThroughput)))
|
||||
}
|
||||
if instance.StorageType != nil {
|
||||
labels[rdsLabelInstanceStorageType] = model.LabelValue(*instance.StorageType)
|
||||
}
|
||||
if instance.StorageVolumeStatus != nil {
|
||||
labels[rdsLabelInstanceStorageVolumeStatus] = model.LabelValue(*instance.StorageVolumeStatus)
|
||||
}
|
||||
if instance.TdeCredentialArn != nil {
|
||||
labels[rdsLabelInstanceTdeCredentialArn] = model.LabelValue(*instance.TdeCredentialArn)
|
||||
}
|
||||
if instance.Timezone != nil {
|
||||
labels[rdsLabelInstanceTimezone] = model.LabelValue(*instance.Timezone)
|
||||
}
|
||||
if instance.UpgradeRolloutOrder != "" {
|
||||
labels[rdsLabelInstanceUpgradeRolloutOrder] = model.LabelValue(instance.UpgradeRolloutOrder)
|
||||
}
|
||||
if instance.DBSubnetGroup != nil && instance.DBSubnetGroup.DBSubnetGroupName != nil {
|
||||
labels[rdsLabelInstanceDBSubnetGroup] = model.LabelValue(*instance.DBSubnetGroup.DBSubnetGroupName)
|
||||
}
|
||||
if instance.DBSystemId != nil {
|
||||
labels[rdsLabelInstanceDBSystemID] = model.LabelValue(*instance.DBSystemId)
|
||||
}
|
||||
if instance.DatabaseInsightsMode != "" {
|
||||
labels[rdsLabelInstanceDatabaseInsightsMode] = model.LabelValue(instance.DatabaseInsightsMode)
|
||||
}
|
||||
|
||||
// Instance tags
|
||||
for _, tag := range instance.TagList {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
labels[model.LabelName(rdsLabelInstanceTag+strutil.SanitizeLabelName(*tag.Key))] = model.LabelValue(*tag.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Set the address label
|
||||
if instance.Endpoint != nil && instance.Endpoint.Address != nil && instance.Endpoint.Port != nil {
|
||||
labels[model.AddressLabel] = model.LabelValue(net.JoinHostPort(*instance.Endpoint.Address, strconv.Itoa(d.cfg.Port)))
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
tg.Targets = append(tg.Targets, labels)
|
||||
mu.Unlock()
|
||||
}
|
||||
}(cluster, instances)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return []*targetgroup.Group{tg}, nil
|
||||
}
|
||||
450
discovery/aws/rds_test.go
Normal file
450
discovery/aws/rds_test.go
Normal file
@ -0,0 +1,450 @@
|
||||
// Copyright The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/rds"
|
||||
"github.com/aws/aws-sdk-go-v2/service/rds/types"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||
)
|
||||
|
||||
// Mock RDS client for testing.
|
||||
type mockRDSClient struct {
|
||||
clusters map[string]types.DBCluster
|
||||
instances map[string][]types.DBInstance
|
||||
}
|
||||
|
||||
func (m *mockRDSClient) DescribeDBClusters(_ context.Context, input *rds.DescribeDBClustersInput, _ ...func(*rds.Options)) (*rds.DescribeDBClustersOutput, error) {
|
||||
var clusters []types.DBCluster
|
||||
|
||||
if input.DBClusterIdentifier != nil {
|
||||
// Specific cluster requested
|
||||
if cluster, ok := m.clusters[*input.DBClusterIdentifier]; ok {
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
} else {
|
||||
// All clusters
|
||||
for _, cluster := range m.clusters {
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
}
|
||||
|
||||
return &rds.DescribeDBClustersOutput{
|
||||
DBClusters: clusters,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockRDSClient) DescribeDBInstances(_ context.Context, input *rds.DescribeDBInstancesInput, _ ...func(*rds.Options)) (*rds.DescribeDBInstancesOutput, error) {
|
||||
var instances []types.DBInstance
|
||||
|
||||
// Check if filtering by cluster
|
||||
if input.Filters != nil {
|
||||
for _, filter := range input.Filters {
|
||||
if filter.Name != nil && *filter.Name == "db-cluster-id" {
|
||||
for _, clusterID := range filter.Values {
|
||||
if clusterInstances, ok := m.instances[clusterID]; ok {
|
||||
instances = append(instances, clusterInstances...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// All instances
|
||||
for _, clusterInstances := range m.instances {
|
||||
instances = append(instances, clusterInstances...)
|
||||
}
|
||||
}
|
||||
|
||||
return &rds.DescribeDBInstancesOutput{
|
||||
DBInstances: instances,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestRDSDiscoveryRefresh(t *testing.T) {
|
||||
testTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
clusters map[string]types.DBCluster
|
||||
instances map[string][]types.DBInstance
|
||||
expectedLabels []model.LabelSet
|
||||
}{
|
||||
{
|
||||
name: "SingleClusterWithInstance",
|
||||
clusters: map[string]types.DBCluster{
|
||||
"arn:aws:rds:us-east-1:123456789012:cluster:test-cluster": {
|
||||
DBClusterArn: aws.String("arn:aws:rds:us-east-1:123456789012:cluster:test-cluster"),
|
||||
DBClusterIdentifier: aws.String("test-cluster"),
|
||||
Engine: aws.String("aurora-postgresql"),
|
||||
EngineVersion: aws.String("15.4"),
|
||||
Status: aws.String("available"),
|
||||
Endpoint: aws.String("test-cluster.cluster-xyz.us-east-1.rds.amazonaws.com"),
|
||||
Port: aws.Int32(5432),
|
||||
MasterUsername: aws.String("admin"),
|
||||
MultiAZ: aws.Bool(true),
|
||||
ClusterCreateTime: aws.Time(testTime),
|
||||
DBClusterMembers: []types.DBClusterMember{
|
||||
{
|
||||
DBInstanceIdentifier: aws.String("test-instance-1"),
|
||||
IsClusterWriter: aws.Bool(true),
|
||||
},
|
||||
},
|
||||
TagList: []types.Tag{
|
||||
{Key: aws.String("Environment"), Value: aws.String("test")},
|
||||
},
|
||||
},
|
||||
},
|
||||
instances: map[string][]types.DBInstance{
|
||||
"arn:aws:rds:us-east-1:123456789012:cluster:test-cluster": {
|
||||
{
|
||||
DBInstanceArn: aws.String("arn:aws:rds:us-east-1:123456789012:db:test-instance-1"),
|
||||
DBInstanceIdentifier: aws.String("test-instance-1"),
|
||||
DBInstanceClass: aws.String("db.r5.large"),
|
||||
DBInstanceStatus: aws.String("available"),
|
||||
Engine: aws.String("aurora-postgresql"),
|
||||
EngineVersion: aws.String("15.4"),
|
||||
AvailabilityZone: aws.String("us-east-1a"),
|
||||
DBClusterIdentifier: aws.String("test-cluster"),
|
||||
PubliclyAccessible: aws.Bool(false),
|
||||
InstanceCreateTime: aws.Time(testTime),
|
||||
Endpoint: &types.Endpoint{
|
||||
Address: aws.String("test-instance-1.xyz.us-east-1.rds.amazonaws.com"),
|
||||
Port: aws.Int32(5432),
|
||||
HostedZoneId: aws.String("Z2R2ITUGPM61AM"),
|
||||
},
|
||||
TagList: []types.Tag{
|
||||
{Key: aws.String("Name"), Value: aws.String("test-instance")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedLabels: []model.LabelSet{
|
||||
{
|
||||
model.AddressLabel: model.LabelValue("test-instance-1.xyz.us-east-1.rds.amazonaws.com:5432"),
|
||||
rdsLabelClusterDBClusterArn: model.LabelValue("arn:aws:rds:us-east-1:123456789012:cluster:test-cluster"),
|
||||
rdsLabelClusterDBClusterIdentifier: model.LabelValue("test-cluster"),
|
||||
rdsLabelClusterEngine: model.LabelValue("aurora-postgresql"),
|
||||
rdsLabelClusterEngineVersion: model.LabelValue("15.4"),
|
||||
rdsLabelClusterStatus: model.LabelValue("available"),
|
||||
rdsLabelClusterEndpoint: model.LabelValue("test-cluster.cluster-xyz.us-east-1.rds.amazonaws.com"),
|
||||
rdsLabelClusterPort: model.LabelValue("5432"),
|
||||
rdsLabelClusterMasterUsername: model.LabelValue("admin"),
|
||||
rdsLabelClusterMultiAZ: model.LabelValue("true"),
|
||||
rdsLabelClusterClusterCreateTime: model.LabelValue(testTime.Format(time.RFC3339)),
|
||||
model.LabelName(rdsLabelClusterTag + "Environment"): model.LabelValue("test"),
|
||||
rdsLabelInstanceDBInstanceArn: model.LabelValue("arn:aws:rds:us-east-1:123456789012:db:test-instance-1"),
|
||||
rdsLabelInstanceDBInstanceIdentifier: model.LabelValue("test-instance-1"),
|
||||
rdsLabelInstanceIsClusterWriter: model.LabelValue("true"),
|
||||
rdsLabelInstanceDBInstanceClass: model.LabelValue("db.r5.large"),
|
||||
rdsLabelInstanceDBInstanceStatus: model.LabelValue("available"),
|
||||
rdsLabelInstanceEngine: model.LabelValue("aurora-postgresql"),
|
||||
rdsLabelInstanceEngineVersion: model.LabelValue("15.4"),
|
||||
rdsLabelInstanceAvailabilityZone: model.LabelValue("us-east-1a"),
|
||||
rdsLabelInstanceDBClusterIdentifier: model.LabelValue("test-cluster"),
|
||||
rdsLabelInstancePubliclyAccessible: model.LabelValue("false"),
|
||||
rdsLabelInstanceInstanceCreateTime: model.LabelValue(testTime.Format(time.RFC3339)),
|
||||
rdsLabelInstanceEndpointAddress: model.LabelValue("test-instance-1.xyz.us-east-1.rds.amazonaws.com"),
|
||||
rdsLabelInstanceEndpointPort: model.LabelValue("5432"),
|
||||
rdsLabelInstanceEndpointHostedZoneID: model.LabelValue("Z2R2ITUGPM61AM"),
|
||||
model.LabelName(rdsLabelInstanceTag + "Name"): model.LabelValue("test-instance"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MultipleInstancesInCluster",
|
||||
clusters: map[string]types.DBCluster{
|
||||
"arn:aws:rds:us-west-2:123456789012:cluster:prod-cluster": {
|
||||
DBClusterArn: aws.String("arn:aws:rds:us-west-2:123456789012:cluster:prod-cluster"),
|
||||
DBClusterIdentifier: aws.String("prod-cluster"),
|
||||
Engine: aws.String("aurora-mysql"),
|
||||
EngineVersion: aws.String("8.0.mysql_aurora.3.04.0"),
|
||||
Status: aws.String("available"),
|
||||
DBClusterMembers: []types.DBClusterMember{
|
||||
{
|
||||
DBInstanceIdentifier: aws.String("prod-instance-1"),
|
||||
IsClusterWriter: aws.Bool(true),
|
||||
},
|
||||
{
|
||||
DBInstanceIdentifier: aws.String("prod-instance-2"),
|
||||
IsClusterWriter: aws.Bool(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
instances: map[string][]types.DBInstance{
|
||||
"arn:aws:rds:us-west-2:123456789012:cluster:prod-cluster": {
|
||||
{
|
||||
DBInstanceArn: aws.String("arn:aws:rds:us-west-2:123456789012:db:prod-instance-1"),
|
||||
DBInstanceIdentifier: aws.String("prod-instance-1"),
|
||||
DBInstanceClass: aws.String("db.r6g.xlarge"),
|
||||
DBInstanceStatus: aws.String("available"),
|
||||
Endpoint: &types.Endpoint{
|
||||
Address: aws.String("prod-instance-1.xyz.us-west-2.rds.amazonaws.com"),
|
||||
Port: aws.Int32(3306),
|
||||
},
|
||||
},
|
||||
{
|
||||
DBInstanceArn: aws.String("arn:aws:rds:us-west-2:123456789012:db:prod-instance-2"),
|
||||
DBInstanceIdentifier: aws.String("prod-instance-2"),
|
||||
DBInstanceClass: aws.String("db.r6g.xlarge"),
|
||||
DBInstanceStatus: aws.String("available"),
|
||||
Endpoint: &types.Endpoint{
|
||||
Address: aws.String("prod-instance-2.xyz.us-west-2.rds.amazonaws.com"),
|
||||
Port: aws.Int32(3306),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedLabels: []model.LabelSet{
|
||||
{
|
||||
model.AddressLabel: model.LabelValue("prod-instance-1.xyz.us-west-2.rds.amazonaws.com:3306"),
|
||||
rdsLabelClusterDBClusterArn: model.LabelValue("arn:aws:rds:us-west-2:123456789012:cluster:prod-cluster"),
|
||||
rdsLabelClusterDBClusterIdentifier: model.LabelValue("prod-cluster"),
|
||||
rdsLabelClusterEngine: model.LabelValue("aurora-mysql"),
|
||||
rdsLabelClusterEngineVersion: model.LabelValue("8.0.mysql_aurora.3.04.0"),
|
||||
rdsLabelClusterStatus: model.LabelValue("available"),
|
||||
rdsLabelInstanceDBInstanceArn: model.LabelValue("arn:aws:rds:us-west-2:123456789012:db:prod-instance-1"),
|
||||
rdsLabelInstanceDBInstanceIdentifier: model.LabelValue("prod-instance-1"),
|
||||
rdsLabelInstanceIsClusterWriter: model.LabelValue("true"),
|
||||
rdsLabelInstanceDBInstanceClass: model.LabelValue("db.r6g.xlarge"),
|
||||
rdsLabelInstanceDBInstanceStatus: model.LabelValue("available"),
|
||||
rdsLabelInstanceEndpointAddress: model.LabelValue("prod-instance-1.xyz.us-west-2.rds.amazonaws.com"),
|
||||
rdsLabelInstanceEndpointPort: model.LabelValue("3306"),
|
||||
},
|
||||
{
|
||||
model.AddressLabel: model.LabelValue("prod-instance-2.xyz.us-west-2.rds.amazonaws.com:3306"),
|
||||
rdsLabelClusterDBClusterArn: model.LabelValue("arn:aws:rds:us-west-2:123456789012:cluster:prod-cluster"),
|
||||
rdsLabelClusterDBClusterIdentifier: model.LabelValue("prod-cluster"),
|
||||
rdsLabelClusterEngine: model.LabelValue("aurora-mysql"),
|
||||
rdsLabelClusterEngineVersion: model.LabelValue("8.0.mysql_aurora.3.04.0"),
|
||||
rdsLabelClusterStatus: model.LabelValue("available"),
|
||||
rdsLabelInstanceDBInstanceArn: model.LabelValue("arn:aws:rds:us-west-2:123456789012:db:prod-instance-2"),
|
||||
rdsLabelInstanceDBInstanceIdentifier: model.LabelValue("prod-instance-2"),
|
||||
rdsLabelInstanceIsClusterWriter: model.LabelValue("false"),
|
||||
rdsLabelInstanceDBInstanceClass: model.LabelValue("db.r6g.xlarge"),
|
||||
rdsLabelInstanceDBInstanceStatus: model.LabelValue("available"),
|
||||
rdsLabelInstanceEndpointAddress: model.LabelValue("prod-instance-2.xyz.us-west-2.rds.amazonaws.com"),
|
||||
rdsLabelInstanceEndpointPort: model.LabelValue("3306"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockClient := &mockRDSClient{
|
||||
clusters: tt.clusters,
|
||||
instances: tt.instances,
|
||||
}
|
||||
|
||||
d := &RDSDiscovery{
|
||||
rds: mockClient,
|
||||
cfg: &RDSSDConfig{
|
||||
Region: "us-east-1",
|
||||
RequestConcurrency: 10,
|
||||
},
|
||||
}
|
||||
|
||||
tg := &targetgroup.Group{}
|
||||
|
||||
// Get all cluster ARNs
|
||||
var clusterARNs []string
|
||||
for arn := range tt.clusters {
|
||||
clusterARNs = append(clusterARNs, arn)
|
||||
}
|
||||
|
||||
clusters, err := d.describeAllDBClusters(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, clusters, len(tt.clusters))
|
||||
|
||||
instances := make(map[string][]types.DBInstance)
|
||||
for _, arn := range clusterARNs {
|
||||
clusterInstances, err := d.describeDBInstances(context.Background(), arn)
|
||||
require.NoError(t, err)
|
||||
instances[arn] = clusterInstances
|
||||
}
|
||||
|
||||
// Build targets like the refresh function does
|
||||
for _, cluster := range clusters {
|
||||
writerMap := make(map[string]bool)
|
||||
for _, member := range cluster.DBClusterMembers {
|
||||
if member.DBInstanceIdentifier != nil && member.IsClusterWriter != nil {
|
||||
writerMap[*member.DBInstanceIdentifier] = *member.IsClusterWriter
|
||||
}
|
||||
}
|
||||
|
||||
clusterInstances := instances[*cluster.DBClusterArn]
|
||||
for _, instance := range clusterInstances {
|
||||
labels := model.LabelSet{}
|
||||
|
||||
// Add basic cluster labels
|
||||
if cluster.DBClusterArn != nil {
|
||||
labels[rdsLabelClusterDBClusterArn] = model.LabelValue(*cluster.DBClusterArn)
|
||||
}
|
||||
if cluster.DBClusterIdentifier != nil {
|
||||
labels[rdsLabelClusterDBClusterIdentifier] = model.LabelValue(*cluster.DBClusterIdentifier)
|
||||
}
|
||||
if cluster.Engine != nil {
|
||||
labels[rdsLabelClusterEngine] = model.LabelValue(*cluster.Engine)
|
||||
}
|
||||
if cluster.EngineVersion != nil {
|
||||
labels[rdsLabelClusterEngineVersion] = model.LabelValue(*cluster.EngineVersion)
|
||||
}
|
||||
if cluster.Status != nil {
|
||||
labels[rdsLabelClusterStatus] = model.LabelValue(*cluster.Status)
|
||||
}
|
||||
if cluster.Endpoint != nil {
|
||||
labels[rdsLabelClusterEndpoint] = model.LabelValue(*cluster.Endpoint)
|
||||
}
|
||||
if cluster.Port != nil {
|
||||
labels[rdsLabelClusterPort] = model.LabelValue(strconv.Itoa(int(*cluster.Port)))
|
||||
}
|
||||
if cluster.MasterUsername != nil {
|
||||
labels[rdsLabelClusterMasterUsername] = model.LabelValue(*cluster.MasterUsername)
|
||||
}
|
||||
if cluster.MultiAZ != nil {
|
||||
labels[rdsLabelClusterMultiAZ] = model.LabelValue(strconv.FormatBool(*cluster.MultiAZ))
|
||||
}
|
||||
if cluster.ClusterCreateTime != nil {
|
||||
labels[rdsLabelClusterClusterCreateTime] = model.LabelValue(cluster.ClusterCreateTime.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
// Cluster tags
|
||||
for _, tag := range cluster.TagList {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
labels[model.LabelName(rdsLabelClusterTag+*tag.Key)] = model.LabelValue(*tag.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Add basic instance labels
|
||||
if instance.DBInstanceArn != nil {
|
||||
labels[rdsLabelInstanceDBInstanceArn] = model.LabelValue(*instance.DBInstanceArn)
|
||||
}
|
||||
if instance.DBInstanceIdentifier != nil {
|
||||
labels[rdsLabelInstanceDBInstanceIdentifier] = model.LabelValue(*instance.DBInstanceIdentifier)
|
||||
if isWriter, found := writerMap[*instance.DBInstanceIdentifier]; found {
|
||||
labels[rdsLabelInstanceIsClusterWriter] = model.LabelValue(strconv.FormatBool(isWriter))
|
||||
}
|
||||
}
|
||||
if instance.DBInstanceClass != nil {
|
||||
labels[rdsLabelInstanceDBInstanceClass] = model.LabelValue(*instance.DBInstanceClass)
|
||||
}
|
||||
if instance.DBInstanceStatus != nil {
|
||||
labels[rdsLabelInstanceDBInstanceStatus] = model.LabelValue(*instance.DBInstanceStatus)
|
||||
}
|
||||
if instance.Engine != nil {
|
||||
labels[rdsLabelInstanceEngine] = model.LabelValue(*instance.Engine)
|
||||
}
|
||||
if instance.EngineVersion != nil {
|
||||
labels[rdsLabelInstanceEngineVersion] = model.LabelValue(*instance.EngineVersion)
|
||||
}
|
||||
if instance.AvailabilityZone != nil {
|
||||
labels[rdsLabelInstanceAvailabilityZone] = model.LabelValue(*instance.AvailabilityZone)
|
||||
}
|
||||
if instance.DBClusterIdentifier != nil {
|
||||
labels[rdsLabelInstanceDBClusterIdentifier] = model.LabelValue(*instance.DBClusterIdentifier)
|
||||
}
|
||||
if instance.PubliclyAccessible != nil {
|
||||
labels[rdsLabelInstancePubliclyAccessible] = model.LabelValue(strconv.FormatBool(*instance.PubliclyAccessible))
|
||||
}
|
||||
if instance.InstanceCreateTime != nil {
|
||||
labels[rdsLabelInstanceInstanceCreateTime] = model.LabelValue(instance.InstanceCreateTime.Format(time.RFC3339))
|
||||
}
|
||||
if instance.Endpoint != nil {
|
||||
if instance.Endpoint.Address != nil {
|
||||
labels[rdsLabelInstanceEndpointAddress] = model.LabelValue(*instance.Endpoint.Address)
|
||||
}
|
||||
if instance.Endpoint.Port != nil {
|
||||
labels[rdsLabelInstanceEndpointPort] = model.LabelValue(strconv.Itoa(int(*instance.Endpoint.Port)))
|
||||
}
|
||||
if instance.Endpoint.HostedZoneId != nil {
|
||||
labels[rdsLabelInstanceEndpointHostedZoneID] = model.LabelValue(*instance.Endpoint.HostedZoneId)
|
||||
}
|
||||
}
|
||||
|
||||
// Instance tags
|
||||
for _, tag := range instance.TagList {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
labels[model.LabelName(rdsLabelInstanceTag+*tag.Key)] = model.LabelValue(*tag.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Set address
|
||||
if instance.Endpoint != nil && instance.Endpoint.Address != nil && instance.Endpoint.Port != nil {
|
||||
labels[model.AddressLabel] = model.LabelValue(net.JoinHostPort(*instance.Endpoint.Address, strconv.Itoa(int(*instance.Endpoint.Port))))
|
||||
}
|
||||
|
||||
tg.Targets = append(tg.Targets, labels)
|
||||
}
|
||||
}
|
||||
|
||||
require.Len(t, tg.Targets, len(tt.expectedLabels))
|
||||
|
||||
// Verify each expected label set is present
|
||||
for _, expectedLabels := range tt.expectedLabels {
|
||||
found := false
|
||||
for _, target := range tg.Targets {
|
||||
if target[model.AddressLabel] == expectedLabels[model.AddressLabel] {
|
||||
found = true
|
||||
// Check all expected labels are present with correct values
|
||||
for key, expectedValue := range expectedLabels {
|
||||
require.Equal(t, expectedValue, target[key], "Label %s mismatch", key)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
require.True(t, found, "Expected target with address %s not found", expectedLabels[model.AddressLabel])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescribeAllDBClusters(t *testing.T) {
|
||||
mockClient := &mockRDSClient{
|
||||
clusters: map[string]types.DBCluster{
|
||||
"arn:aws:rds:us-east-1:123456789012:cluster:cluster-1": {
|
||||
DBClusterArn: aws.String("arn:aws:rds:us-east-1:123456789012:cluster:cluster-1"),
|
||||
DBClusterIdentifier: aws.String("cluster-1"),
|
||||
},
|
||||
"arn:aws:rds:us-east-1:123456789012:cluster:cluster-2": {
|
||||
DBClusterArn: aws.String("arn:aws:rds:us-east-1:123456789012:cluster:cluster-2"),
|
||||
DBClusterIdentifier: aws.String("cluster-2"),
|
||||
},
|
||||
},
|
||||
instances: map[string][]types.DBInstance{},
|
||||
}
|
||||
|
||||
d := &RDSDiscovery{
|
||||
rds: mockClient,
|
||||
cfg: &RDSSDConfig{
|
||||
RequestConcurrency: 10,
|
||||
},
|
||||
}
|
||||
|
||||
clusters, err := d.describeAllDBClusters(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, clusters, 2)
|
||||
require.Contains(t, clusters, "arn:aws:rds:us-east-1:123456789012:cluster:cluster-1")
|
||||
require.Contains(t, clusters, "arn:aws:rds:us-east-1:123456789012:cluster:cluster-2")
|
||||
}
|
||||
@ -1135,11 +1135,177 @@ The following meta labels are available on targets during [relabeling](#relabel_
|
||||
* `__meta_elasticache_cache_cluster_node_endpoint_port`: cache node endpoint port
|
||||
* `__meta_elasticache_cache_cluster_tag_<tagkey>`: each cache cluster tag value, keyed by tag name
|
||||
|
||||
#### `rds`
|
||||
|
||||
The `rds` role discovers targets from [AWS RDS](https://aws.amazon.com/rds/)
|
||||
database instances within clusters. One target is created for each DB instance
|
||||
within the specified clusters. The endpoint address and port of each instance is used by default.
|
||||
|
||||
The IAM credentials used must have the `rds:DescribeDBClusters` and `rds:DescribeDBInstances`
|
||||
permissions to discover scrape targets.
|
||||
|
||||
The following meta labels are available on targets during [relabeling](#relabel_config):
|
||||
|
||||
**Cluster labels:**
|
||||
|
||||
* `__meta_rds_cluster_activity_stream_kinesis_stream_name`: the name of the Amazon Kinesis data stream used for database activity stream
|
||||
* `__meta_rds_cluster_activity_stream_kms_key_id`: the AWS KMS key identifier used for encrypting the database activity stream
|
||||
* `__meta_rds_cluster_activity_stream_mode`: the mode of the database activity stream (sync or async)
|
||||
* `__meta_rds_cluster_activity_stream_status`: the status of the database activity stream
|
||||
* `__meta_rds_cluster_allocated_storage`: the allocated storage size in gibibytes (GiB)
|
||||
* `__meta_rds_cluster_arn`: the Amazon Resource Name (ARN) of the DB cluster
|
||||
* `__meta_rds_cluster_auto_minor_version_upgrade`: whether automatic minor version upgrades are enabled
|
||||
* `__meta_rds_cluster_automatic_restart_time`: the time when a stopped cluster will be automatically restarted
|
||||
* `__meta_rds_cluster_aws_backup_recovery_point_arn`: the ARN of the recovery point in AWS Backup
|
||||
* `__meta_rds_cluster_backtrack_consumed_change_records`: the number of change records stored for backtrack
|
||||
* `__meta_rds_cluster_backtrack_window`: the target backtrack window in hours
|
||||
* `__meta_rds_cluster_backup_retention_period`: the number of days for which automated backups are retained
|
||||
* `__meta_rds_cluster_capacity`: the current capacity of an Aurora Serverless DB cluster
|
||||
* `__meta_rds_cluster_character_set_name`: the name of the character set
|
||||
* `__meta_rds_cluster_clone_group_id`: the ID of the clone group
|
||||
* `__meta_rds_cluster_cluster_create_time`: the time when the DB cluster was created
|
||||
* `__meta_rds_cluster_cluster_scalability_type`: the scalability type of the cluster
|
||||
* `__meta_rds_cluster_copy_tags_to_snapshot`: whether tags are copied from the cluster to snapshots
|
||||
* `__meta_rds_cluster_cross_account_clone`: whether the DB cluster is a cross-account clone
|
||||
* `__meta_rds_cluster_database_insights_mode`: the mode of Database Insights
|
||||
* `__meta_rds_cluster_database_name`: the database name
|
||||
* `__meta_rds_cluster_db_system_id`: the Oracle system ID (Oracle SID)
|
||||
* `__meta_rds_cluster_deletion_protection`: whether deletion protection is enabled
|
||||
* `__meta_rds_cluster_earliest_backtrack_time`: the earliest time to which a database can be restored with backtrack
|
||||
* `__meta_rds_cluster_earliest_restorable_time`: the earliest time to which a database can be restored
|
||||
* `__meta_rds_cluster_endpoint`: the endpoint of the DB cluster
|
||||
* `__meta_rds_cluster_engine_lifecycle_support`: the engine lifecycle support value
|
||||
* `__meta_rds_cluster_engine_mode`: the engine mode of the cluster (provisioned, serverless, etc.)
|
||||
* `__meta_rds_cluster_engine_version`: the version of the database engine
|
||||
* `__meta_rds_cluster_engine`: the database engine of the DB cluster
|
||||
* `__meta_rds_cluster_global_cluster_identifier`: the identifier of the global cluster
|
||||
* `__meta_rds_cluster_global_write_forwarding_requested`: whether global write forwarding is requested
|
||||
* `__meta_rds_cluster_global_write_forwarding_status`: the status of global write forwarding
|
||||
* `__meta_rds_cluster_hosted_zone_id`: the Route 53 hosted zone ID
|
||||
* `__meta_rds_cluster_http_endpoint_enabled`: whether the HTTP endpoint is enabled
|
||||
* `__meta_rds_cluster_iam_database_authentication_enabled`: whether the DB cluster has IAM database authentication enabled
|
||||
* `__meta_rds_cluster_identifier`: the identifier of the DB cluster
|
||||
* `__meta_rds_cluster_instance_class`: the compute and memory capacity class of the DB cluster
|
||||
* `__meta_rds_cluster_io_optimized_next_allowed_modification_time`: the time when the next IO optimization configuration change is allowed
|
||||
* `__meta_rds_cluster_iops`: the provisioned IOPS (I/O operations per second) value
|
||||
* `__meta_rds_cluster_kms_key_id`: the AWS KMS key identifier for the encrypted cluster
|
||||
* `__meta_rds_cluster_latest_restorable_time`: the latest time to which a database can be restored
|
||||
* `__meta_rds_cluster_local_write_forwarding_status`: the status of local write forwarding
|
||||
* `__meta_rds_cluster_master_username`: the master username
|
||||
* `__meta_rds_cluster_monitoring_interval`: the interval in seconds between enhanced monitoring metrics collection
|
||||
* `__meta_rds_cluster_monitoring_role_arn`: the ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch
|
||||
* `__meta_rds_cluster_multi_az`: whether the DB cluster is multi-AZ
|
||||
* `__meta_rds_cluster_network_type`: the network type (IPV4 or DUAL)
|
||||
* `__meta_rds_cluster_parameter_group`: the name of the DB cluster parameter group
|
||||
* `__meta_rds_cluster_percent_progress`: the progress percentage of the DB cluster operation
|
||||
* `__meta_rds_cluster_performance_insights_enabled`: whether Performance Insights is enabled
|
||||
* `__meta_rds_cluster_performance_insights_kms_key_id`: the AWS KMS key identifier for encrypting Performance Insights data
|
||||
* `__meta_rds_cluster_performance_insights_retention_period`: the retention period for Performance Insights data
|
||||
* `__meta_rds_cluster_port`: the port the DB cluster is listening on
|
||||
* `__meta_rds_cluster_preferred_backup_window`: the daily time range during which automated backups are created
|
||||
* `__meta_rds_cluster_preferred_maintenance_window`: the weekly time range during which system maintenance can occur
|
||||
* `__meta_rds_cluster_publicly_accessible`: whether the DB cluster is publicly accessible
|
||||
* `__meta_rds_cluster_reader_endpoint`: the reader endpoint of the DB cluster
|
||||
* `__meta_rds_cluster_replication_source_identifier`: the identifier of the source DB cluster if this is a read replica
|
||||
* `__meta_rds_cluster_resource_id`: the AWS Region-unique immutable identifier for the DB cluster
|
||||
* `__meta_rds_cluster_serverless_v2_platform_version`: the platform version of the Aurora Serverless v2 DB cluster
|
||||
* `__meta_rds_cluster_status`: the status of the DB cluster
|
||||
* `__meta_rds_cluster_storage_encrypted`: whether the DB cluster is storage encrypted
|
||||
* `__meta_rds_cluster_storage_encryption_type`: the storage encryption type
|
||||
* `__meta_rds_cluster_storage_throughput`: the storage throughput in MiBps
|
||||
* `__meta_rds_cluster_storage_type`: the storage type
|
||||
* `__meta_rds_cluster_subnet_group`: the name of the subnet group associated with the DB cluster
|
||||
* `__meta_rds_cluster_tag_<tagkey>`: each tag value of the DB cluster
|
||||
* `__meta_rds_cluster_upgrade_rollout_order`: the upgrade rollout order
|
||||
|
||||
**Instance labels:**
|
||||
|
||||
* `__meta_rds_instance_activity_stream_engine_native_audit_fields_included`: whether engine-native audit fields are included in the database activity stream
|
||||
* `__meta_rds_instance_activity_stream_kinesis_stream_name`: the name of the Amazon Kinesis data stream used for the database activity stream
|
||||
* `__meta_rds_instance_activity_stream_kms_key_id`: the AWS KMS key identifier used for encrypting the database activity stream
|
||||
* `__meta_rds_instance_activity_stream_mode`: the mode of the database activity stream (sync or async)
|
||||
* `__meta_rds_instance_activity_stream_policy_status`: the policy status of the database activity stream
|
||||
* `__meta_rds_instance_activity_stream_status`: the status of the database activity stream
|
||||
* `__meta_rds_instance_allocated_storage`: the allocated storage size in gibibytes (GiB)
|
||||
* `__meta_rds_instance_arn`: the Amazon Resource Name (ARN) of the DB instance
|
||||
* `__meta_rds_instance_auto_minor_version_upgrade`: whether automatic minor version upgrades are enabled
|
||||
* `__meta_rds_instance_automatic_restart_time`: the time when a stopped instance will be automatically restarted
|
||||
* `__meta_rds_instance_automation_mode`: the automation mode of the instance
|
||||
* `__meta_rds_instance_availability_zone`: the availability zone of the DB instance
|
||||
* `__meta_rds_instance_aws_backup_recovery_point_arn`: the ARN of the recovery point in AWS Backup
|
||||
* `__meta_rds_instance_backup_retention_period`: the number of days for which automated backups are retained
|
||||
* `__meta_rds_instance_backup_target`: the backup target (region or outposts)
|
||||
* `__meta_rds_instance_ca_certificate_identifier`: the identifier of the CA certificate for the DB instance
|
||||
* `__meta_rds_instance_character_set_name`: the name of the character set
|
||||
* `__meta_rds_instance_class`: the compute and memory capacity class of the DB instance
|
||||
* `__meta_rds_instance_copy_tags_to_snapshot`: whether tags are copied from the instance to snapshots
|
||||
* `__meta_rds_instance_custom_iam_instance_profile`: the instance profile associated with the underlying Amazon EC2 instance
|
||||
* `__meta_rds_instance_customer_owned_ip_enabled`: whether a customer-owned IP address (CoIP) is enabled
|
||||
* `__meta_rds_instance_database_insights_mode`: the mode of Database Insights
|
||||
* `__meta_rds_instance_db_cluster_identifier`: the identifier of the DB cluster this instance is a member of
|
||||
* `__meta_rds_instance_db_name`: the database name
|
||||
* `__meta_rds_instance_db_system_id`: the Oracle system ID (Oracle SID)
|
||||
* `__meta_rds_instance_dedicated_log_volume`: whether the DB instance has a dedicated log volume
|
||||
* `__meta_rds_instance_deletion_protection`: whether deletion protection is enabled
|
||||
* `__meta_rds_instance_endpoint_address`: the DNS address of the DB instance
|
||||
* `__meta_rds_instance_endpoint_hosted_zone_id`: the Route 53 hosted zone ID of the endpoint
|
||||
* `__meta_rds_instance_endpoint_port`: the port that the DB instance listens on
|
||||
* `__meta_rds_instance_engine_lifecycle_support`: the engine lifecycle support value
|
||||
* `__meta_rds_instance_engine_version`: the version of the database engine
|
||||
* `__meta_rds_instance_engine`: the database engine that the DB instance uses
|
||||
* `__meta_rds_instance_enhanced_monitoring_resource_arn`: the ARN of the Amazon CloudWatch Logs log stream for enhanced monitoring
|
||||
* `__meta_rds_instance_iam_database_authentication_enabled`: whether IAM database authentication is enabled
|
||||
* `__meta_rds_instance_identifier`: the identifier of the DB instance
|
||||
* `__meta_rds_instance_instance_create_time`: the time when the DB instance was created
|
||||
* `__meta_rds_instance_iops`: the provisioned IOPS (I/O operations per second) value
|
||||
* `__meta_rds_instance_is_cluster_writer`: whether the instance is the cluster writer (true/false)
|
||||
* `__meta_rds_instance_is_storage_config_upgrade_available`: whether a storage configuration upgrade is available
|
||||
* `__meta_rds_instance_kms_key_id`: the AWS KMS key identifier for the encrypted instance
|
||||
* `__meta_rds_instance_latest_restorable_time`: the latest time to which a database can be restored
|
||||
* `__meta_rds_instance_license_model`: the license model information
|
||||
* `__meta_rds_instance_listener_endpoint_address`: the DNS address of the listener endpoint
|
||||
* `__meta_rds_instance_listener_endpoint_hosted_zone_id`: the Route 53 hosted zone ID of the listener endpoint
|
||||
* `__meta_rds_instance_listener_endpoint_port`: the port that the listener endpoint listens on
|
||||
* `__meta_rds_instance_master_username`: the master username
|
||||
* `__meta_rds_instance_max_allocated_storage`: the upper limit in gibibytes to which storage can be scaled automatically
|
||||
* `__meta_rds_instance_monitoring_interval`: the interval in seconds between enhanced monitoring metrics collection
|
||||
* `__meta_rds_instance_monitoring_role_arn`: the ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch
|
||||
* `__meta_rds_instance_multi_az`: whether the DB instance is a Multi-AZ deployment
|
||||
* `__meta_rds_instance_multi_tenant`: whether the instance is in a multi-tenant configuration
|
||||
* `__meta_rds_instance_nchar_character_set_name`: the national character set name
|
||||
* `__meta_rds_instance_network_type`: the network type (IPV4 or DUAL)
|
||||
* `__meta_rds_instance_percent_progress`: the progress percentage of the DB instance operation
|
||||
* `__meta_rds_instance_performance_insights_enabled`: whether Performance Insights is enabled
|
||||
* `__meta_rds_instance_performance_insights_kms_key_id`: the AWS KMS key identifier for encrypting Performance Insights data
|
||||
* `__meta_rds_instance_performance_insights_retention_period`: the retention period for Performance Insights data
|
||||
* `__meta_rds_instance_port`: the port that the DB instance listens on
|
||||
* `__meta_rds_instance_preferred_backup_window`: the daily time range during which automated backups are created
|
||||
* `__meta_rds_instance_preferred_maintenance_window`: the weekly time range during which system maintenance can occur
|
||||
* `__meta_rds_instance_promotion_tier`: the order in which an Aurora replica is promoted to primary instance after a failure
|
||||
* `__meta_rds_instance_publicly_accessible`: whether the DB instance is publicly accessible
|
||||
* `__meta_rds_instance_read_replica_source_db_cluster_identifier`: the identifier of the source DB cluster if this instance is a read replica
|
||||
* `__meta_rds_instance_read_replica_source_db_instance_identifier`: the identifier of the source DB instance if this instance is a read replica
|
||||
* `__meta_rds_instance_replica_mode`: the replica mode (open-read-only or mounted)
|
||||
* `__meta_rds_instance_resource_id`: the AWS Region-unique immutable identifier for the DB instance
|
||||
* `__meta_rds_instance_resume_full_automation_mode_time`: the time when the DB instance will resume full automation
|
||||
* `__meta_rds_instance_secondary_availability_zone`: the secondary availability zone for Multi-AZ instances
|
||||
* `__meta_rds_instance_status`: the status of the DB instance
|
||||
* `__meta_rds_instance_storage_encrypted`: whether the DB instance is storage encrypted
|
||||
* `__meta_rds_instance_storage_encryption_type`: the storage encryption type
|
||||
* `__meta_rds_instance_storage_throughput`: the storage throughput in MiBps
|
||||
* `__meta_rds_instance_storage_type`: the storage type
|
||||
* `__meta_rds_instance_storage_volume_status`: the status of the storage volume
|
||||
* `__meta_rds_instance_subnet_group`: the name of the subnet group associated with the DB instance
|
||||
* `__meta_rds_instance_tag_<tagkey>`: each tag value of the DB instance
|
||||
* `__meta_rds_instance_tde_credential_arn`: the ARN for the TDE encryption key
|
||||
* `__meta_rds_instance_timezone`: the time zone of the DB instance
|
||||
* `__meta_rds_instance_upgrade_rollout_order`: the upgrade rollout order
|
||||
|
||||
See below for the configuration options for AWS discovery:
|
||||
|
||||
```yaml
|
||||
# The AWS role to use for service discovery.
|
||||
# Must be one of: ec2, lightsail, ecs, msk, or elasticache.
|
||||
# Must be one of: ec2, lightsail, ecs, msk, elasticache, or rds.
|
||||
role: <string>
|
||||
|
||||
# The AWS region. If blank, the region from the instance metadata is used.
|
||||
@ -1175,7 +1341,7 @@ filters:
|
||||
[ - name: <string>
|
||||
values: <string>, [...] ]
|
||||
|
||||
# List of ECS, ElastiCache, or MSK cluster identifiers (ecs, elasticache, and msk roles only) to discover.
|
||||
# List of ECS, ElastiCache, MSK, or RDS cluster identifiers (ecs, elasticache, msk, and rds roles only) to discover.
|
||||
# A List of ARNs of clusters to discover. If empty, all clusters in the region are discovered.
|
||||
# This can significantly improve performance when you only need to monitor specific clusters/caches.
|
||||
[ clusters: [<string>, ...] ]
|
||||
|
||||
11
go.mod
11
go.mod
@ -11,7 +11,7 @@ require (
|
||||
github.com/KimMachineGun/automemlimit v0.7.5
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.1
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.9
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.9
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.290.0
|
||||
@ -19,6 +19,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.51.9
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.48.0
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.11
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.116.1
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6
|
||||
github.com/aws/smithy-go v1.24.1
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3
|
||||
@ -143,11 +144,11 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
|
||||
22
go.sum
22
go.sum
@ -49,18 +49,18 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.2 h1:LuT2rzqNQsauaGkPK/7813XxcZ3o3yePY0Iy891T2ls=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.2/go.mod h1:IvvlAZQXvTXznUPfRVfryiG1fbzE2NGK6m9u39YQ+S4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.9 h1:ktda/mtAydeObvJXlHzyGpK1xcsLaP16zfUPDGoW90A=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.9/go.mod h1:U+fCQ+9QKsLW786BCfEjYRj34VVTbPdsLP3CHSYXMOI=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.9 h1:sWvTKsyrMlJGEuj/WgrwilpoJ6Xa1+KhIpGdzw7mMU8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.9/go.mod h1:+J44MBhmfVY/lETFiKI+klz0Vym2aCmIjqgClMmW82w=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 h1:F43zk1vemYIqPAwhjTjYIz0irU2EY7sOb/F5eJ3HuyM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18/go.mod h1:w1jdlZXrGKaJcNoL+Nnrj+k5wlpGXqnNrKoP22HvAug=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoyP2slHsGArMxeiiaoPN5QZH6YQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.290.0 h1:Ub4CvLWf8wEQ7/pEiqXM9tTsHXf2BokPLwbqEvrmAq0=
|
||||
@ -69,14 +69,16 @@ github.com/aws/aws-sdk-go-v2/service/ecs v1.72.0 h1:hggRKpv26DpYMOik3wWo1Ty5MkAN
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.72.0/go.mod h1:pMlGFDpHoLTJOIZHGdJOAWmi+xeIlQXuFTuQxs1epYE=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.51.9 h1:hTgZLyNoDWphZUtTtcvQh0LP6TZO0mtdSfZK/GObDLk=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.51.9/go.mod h1:91RkIYy9ubykxB50XGYDsbljLZnrZ6rp/Urt4rZrbwQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.48.0 h1:CKRWqysU9INeoi0nTI9gDzDAJk+GatzFduVYxT/wkrw=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.48.0/go.mod h1:tWnHS64fg5ydLHivFlCAtEh/1iMNzr56QsH3F+UTwD4=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.11 h1:VM5e5M39zRSs+aT0O9SoxHjUXqXxhbw3Yi0FdMQWPIc=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.11/go.mod h1:0jvzYPIQGCpnY/dmdaotTk2JH4QuBlnW0oeyrcGLWJ4=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.116.1 h1:a5PMhM3lOcu2DKgvYGjhCDToKQnz9VEUo9iSc5+DsyA=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.116.1/go.mod h1:bMaMwbVQ96bx42kDw/Ko+YiDyT/UCotPO+1RDp6lq7E=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 h1:+VTRawC4iVY58pS/lzpo0lnoa/SYNGF4/B/3/U5ro8Y=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user