@@ -21,6 +21,7 @@ import (
21
21
"time"
22
22
23
23
"github.com/aws/aws-sdk-go/aws"
24
+ "github.com/aws/aws-sdk-go/aws/awserr"
24
25
"github.com/aws/aws-sdk-go/aws/credentials"
25
26
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
26
27
"github.com/aws/aws-sdk-go/aws/ec2metadata"
@@ -129,66 +130,71 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
129
130
// the Discoverer interface.
130
131
type Discovery struct {
131
132
* refresh.Discovery
132
- region string
133
- interval time.Duration
134
- port int
135
- filters []* Filter
136
- ec2 * ec2.EC2
133
+ cfg * SDConfig
134
+ ec2 * ec2.EC2
137
135
}
138
136
139
137
// NewDiscovery returns a new EC2Discovery which periodically refreshes its targets.
140
138
func NewDiscovery (conf * SDConfig , logger log.Logger ) * Discovery {
141
- creds := credentials .NewStaticCredentials (conf .AccessKey , string (conf .SecretKey ), "" )
142
- if conf .AccessKey == "" && conf .SecretKey == "" {
143
- creds = nil
144
- }
145
139
if logger == nil {
146
140
logger = log .NewNopLogger ()
147
141
}
142
+ d := & Discovery {
143
+ cfg : conf ,
144
+ }
145
+ d .Discovery = refresh .NewDiscovery (
146
+ logger ,
147
+ "ec2" ,
148
+ time .Duration (d .cfg .RefreshInterval ),
149
+ d .refresh ,
150
+ )
151
+ return d
152
+ }
153
+
154
+ func (d * Discovery ) ec2Client () (* ec2.EC2 , error ) {
155
+ if d .ec2 != nil {
156
+ return d .ec2 , nil
157
+ }
158
+
159
+ creds := credentials .NewStaticCredentials (d .cfg .AccessKey , string (d .cfg .SecretKey ), "" )
160
+ if d .cfg .AccessKey == "" && d .cfg .SecretKey == "" {
161
+ creds = nil
162
+ }
148
163
149
164
sess , err := session .NewSessionWithOptions (session.Options {
150
165
Config : aws.Config {
151
- Endpoint : & conf .Endpoint ,
152
- Region : & conf .Region ,
166
+ Endpoint : & d . cfg .Endpoint ,
167
+ Region : & d . cfg .Region ,
153
168
Credentials : creds ,
154
169
},
155
- Profile : conf .Profile ,
170
+ Profile : d . cfg .Profile ,
156
171
})
157
172
if err != nil {
158
- return nil
173
+ return nil , errors . Wrap ( err , "could not create aws session" )
159
174
}
160
175
161
- var ec2s * ec2.EC2
162
- if conf .RoleARN != "" {
163
- creds := stscreds .NewCredentials (sess , conf .RoleARN )
164
- ec2s = ec2 .New (sess , & aws.Config {Credentials : creds })
176
+ if d .cfg .RoleARN != "" {
177
+ creds := stscreds .NewCredentials (sess , d .cfg .RoleARN )
178
+ d .ec2 = ec2 .New (sess , & aws.Config {Credentials : creds })
165
179
} else {
166
- ec2s = ec2 .New (sess )
180
+ d . ec2 = ec2 .New (sess )
167
181
}
168
182
169
- d := & Discovery {
170
- region : conf .Region ,
171
- filters : conf .Filters ,
172
- interval : time .Duration (conf .RefreshInterval ),
173
- port : conf .Port ,
174
- ec2 : ec2s ,
175
- }
176
- d .Discovery = refresh .NewDiscovery (
177
- logger ,
178
- "ec2" ,
179
- time .Duration (conf .RefreshInterval ),
180
- d .refresh ,
181
- )
182
- return d
183
+ return d .ec2 , nil
183
184
}
184
185
185
186
func (d * Discovery ) refresh (ctx context.Context ) ([]* targetgroup.Group , error ) {
187
+ ec2Client , err := d .ec2Client ()
188
+ if err != nil {
189
+ return nil , err
190
+ }
191
+
186
192
tg := & targetgroup.Group {
187
- Source : d .region ,
193
+ Source : d .cfg . Region ,
188
194
}
189
195
190
196
var filters []* ec2.Filter
191
- for _ , f := range d .filters {
197
+ for _ , f := range d .cfg . Filters {
192
198
filters = append (filters , & ec2.Filter {
193
199
Name : aws .String (f .Name ),
194
200
Values : aws .StringSlice (f .Values ),
@@ -197,7 +203,7 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
197
203
198
204
input := & ec2.DescribeInstancesInput {Filters : filters }
199
205
200
- if err := d . ec2 .DescribeInstancesPagesWithContext (ctx , input , func (p * ec2.DescribeInstancesOutput , lastPage bool ) bool {
206
+ if err := ec2Client .DescribeInstancesPagesWithContext (ctx , input , func (p * ec2.DescribeInstancesOutput , lastPage bool ) bool {
201
207
for _ , r := range p .Reservations {
202
208
for _ , inst := range r .Instances {
203
209
if inst .PrivateIpAddress == nil {
@@ -215,7 +221,7 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
215
221
if inst .PrivateDnsName != nil {
216
222
labels [ec2LabelPrivateDNS ] = model .LabelValue (* inst .PrivateDnsName )
217
223
}
218
- addr := net .JoinHostPort (* inst .PrivateIpAddress , fmt .Sprintf ("%d" , d .port ))
224
+ addr := net .JoinHostPort (* inst .PrivateIpAddress , fmt .Sprintf ("%d" , d .cfg . Port ))
219
225
labels [model .AddressLabel ] = model .LabelValue (addr )
220
226
221
227
if inst .Platform != nil {
@@ -285,6 +291,9 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
285
291
}
286
292
return true
287
293
}); err != nil {
294
+ if awsErr , ok := err .(awserr.Error ); ok && (awsErr .Code () == "AuthFailure" || awsErr .Code () == "UnauthorizedOperation" ) {
295
+ d .ec2 = nil
296
+ }
288
297
return nil , errors .Wrap (err , "could not describe instances" )
289
298
}
290
299
return []* targetgroup.Group {tg }, nil
0 commit comments