package aws
import (
"errors"
"time"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/grafana/agent/component"
"github.com/grafana/agent/component/discovery"
"github.com/grafana/agent/pkg/river/rivertypes"
promcfg "github.com/prometheus/common/config"
"github.com/prometheus/common/model"
promaws "github.com/prometheus/prometheus/discovery/aws"
)
func init() {
component.Register(component.Registration{
Name: "discovery.ec2",
Args: EC2Arguments{},
Exports: discovery.Exports{},
Build: func(opts component.Options, args component.Arguments) (component.Component, error) {
return NewEC2(opts, args.(EC2Arguments))
},
})
}
type EC2Filter struct {
Name string `river:"name,attr"`
Values []string `river:"values,attr"`
}
type EC2Arguments struct {
Endpoint string `river:"endpoint,attr,optional"`
Region string `river:"region,attr,optional"`
AccessKey string `river:"access_key,attr,optional"`
SecretKey rivertypes.Secret `river:"secret_key,attr,optional"`
Profile string `river:"profile,attr,optional"`
RoleARN string `river:"role_arn,attr,optional"`
RefreshInterval time.Duration `river:"refresh_interval,attr,optional"`
Port int `river:"port,attr,optional"`
Filters []*EC2Filter `river:"filter,block,optional"`
}
func (args EC2Arguments) Convert() *promaws.EC2SDConfig {
cfg := &promaws.EC2SDConfig{
Endpoint: args.Endpoint,
Region: args.Region,
AccessKey: args.AccessKey,
SecretKey: promcfg.Secret(args.SecretKey),
Profile: args.Profile,
RoleARN: args.RoleARN,
RefreshInterval: model.Duration(args.RefreshInterval),
Port: args.Port,
}
for _, f := range args.Filters {
cfg.Filters = append(cfg.Filters, &promaws.EC2Filter{
Name: f.Name,
Values: f.Values,
})
}
return cfg
}
var DefaultEC2SDConfig = EC2Arguments{
Port: 80,
RefreshInterval: 60 * time.Second,
}
func (args *EC2Arguments) UnmarshalRiver(f func(interface{}) error) error {
*args = DefaultEC2SDConfig
type arguments EC2Arguments
if err := f((*arguments)(args)); err != nil {
return err
}
if args.Region == "" {
sess, err := session.NewSession()
if err != nil {
return err
}
metadata := ec2metadata.New(sess)
region, err := metadata.Region()
if err != nil {
return errors.New("EC2 SD configuration requires a region")
}
args.Region = region
}
for _, f := range args.Filters {
if len(f.Values) == 0 {
return errors.New("EC2 SD configuration filter values cannot be empty")
}
}
return nil
}
func NewEC2(opts component.Options, args EC2Arguments) (component.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
conf := args.(EC2Arguments).Convert()
return promaws.NewEC2Discovery(conf, opts.Logger), nil
})
}