Skip to content

Commit 66402db

Browse files
authored
Misleading 404 logs in IMDS mode when querying EC2 Metadata without a public IP (#1058)
* assume public ip and hostname ec2 metadata can be absent Signed-off-by: Xabier Napal <xabier.napal@dvzr.io> * add ec2metadata new tests to check for optional paths Signed-off-by: Xabier Napal <xabier.napal@dvzr.io> --------- Signed-off-by: Xabier Napal <xabier.napal@dvzr.io>
1 parent bb31beb commit 66402db

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

pkg/ec2metadata/ec2metadata.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func (e *Service) GetASGTargetLifecycleState() (state string, err error) {
218218
}
219219

220220
// GetMetadataInfo generic function for retrieving ec2 metadata
221-
func (e *Service) GetMetadataInfo(path string) (info string, err error) {
221+
func (e *Service) GetMetadataInfo(path string, allowMissing bool) (info string, err error) {
222222
metadataInfo := ""
223223
resp, err := e.Request(path)
224224
if err != nil {
@@ -232,8 +232,12 @@ func (e *Service) GetMetadataInfo(path string) (info string, err error) {
232232
}
233233
metadataInfo = string(body)
234234
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
235-
log.Info().Msgf("Metadata response status code: %d. Body: %s", resp.StatusCode, metadataInfo)
236-
return "", fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
235+
if resp.StatusCode != 404 || !allowMissing {
236+
log.Info().Msgf("Metadata response status code: %d. Body: %s", resp.StatusCode, metadataInfo)
237+
return "", fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
238+
} else {
239+
return "", nil
240+
}
237241
}
238242
}
239243
return metadataInfo, nil
@@ -351,26 +355,26 @@ func retry(attempts int, sleep time.Duration, httpReq func() (*http.Response, er
351355
// GetNodeMetadata attempts to gather additional ec2 instance information from the metadata service
352356
func (e *Service) GetNodeMetadata() NodeMetadata {
353357
metadata := NodeMetadata{}
354-
identityDoc, err := e.GetMetadataInfo(IdentityDocPath)
358+
identityDoc, err := e.GetMetadataInfo(IdentityDocPath, false)
355359
if err != nil {
356360
log.Err(err).Msg("Unable to fetch metadata from IMDS")
357361
return metadata
358362
}
359363
err = json.NewDecoder(strings.NewReader(identityDoc)).Decode(&metadata)
360364
if err != nil {
361365
log.Warn().Msg("Unable to fetch instance identity document from ec2 metadata")
362-
metadata.InstanceID, _ = e.GetMetadataInfo(InstanceIDPath)
363-
metadata.InstanceType, _ = e.GetMetadataInfo(InstanceTypePath)
364-
metadata.LocalIP, _ = e.GetMetadataInfo(LocalIPPath)
365-
metadata.AvailabilityZone, _ = e.GetMetadataInfo(AZPlacementPath)
366+
metadata.InstanceID, _ = e.GetMetadataInfo(InstanceIDPath, false)
367+
metadata.InstanceType, _ = e.GetMetadataInfo(InstanceTypePath, false)
368+
metadata.LocalIP, _ = e.GetMetadataInfo(LocalIPPath, false)
369+
metadata.AvailabilityZone, _ = e.GetMetadataInfo(AZPlacementPath, false)
366370
if len(metadata.AvailabilityZone) > 1 {
367371
metadata.Region = metadata.AvailabilityZone[0 : len(metadata.AvailabilityZone)-1]
368372
}
369373
}
370-
metadata.InstanceLifeCycle, _ = e.GetMetadataInfo(InstanceLifeCycle)
371-
metadata.LocalHostname, _ = e.GetMetadataInfo(LocalHostnamePath)
372-
metadata.PublicHostname, _ = e.GetMetadataInfo(PublicHostnamePath)
373-
metadata.PublicIP, _ = e.GetMetadataInfo(PublicIPPath)
374+
metadata.InstanceLifeCycle, _ = e.GetMetadataInfo(InstanceLifeCycle, false)
375+
metadata.LocalHostname, _ = e.GetMetadataInfo(LocalHostnamePath, false)
376+
metadata.PublicHostname, _ = e.GetMetadataInfo(PublicHostnamePath, true)
377+
metadata.PublicIP, _ = e.GetMetadataInfo(PublicIPPath, true)
374378

375379
log.Info().Interface("metadata", metadata).Msg("Startup Metadata Retrieved")
376380

pkg/ec2metadata/ec2metadata_test.go

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,16 +609,66 @@ func TestGetMetadataServiceRequest404(t *testing.T) {
609609
// Use URL from our local test server
610610
imds := ec2metadata.New(server.URL, 1)
611611

612-
_, err := imds.GetMetadataInfo(requestPath)
612+
_, err := imds.GetMetadataInfo(requestPath, false)
613613

614-
h.Assert(t, err != nil, "Expected error to be nil but it was not")
614+
h.Assert(t, err != nil, "Error expected because request errored with 404")
615+
}
616+
617+
func TestGetMetadataServiceRequest404AllowMissing(t *testing.T) {
618+
var requestPath string = "/latest/meta-data/instance-type"
619+
620+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
621+
rw.Header().Add("X-aws-ec2-metadata-token-ttl-seconds", "100")
622+
if req.URL.String() == "/latest/api/token" {
623+
rw.WriteHeader(200)
624+
_, err := rw.Write([]byte(`token`))
625+
h.Ok(t, err)
626+
return
627+
}
628+
h.Equals(t, req.Header.Get("X-aws-ec2-metadata-token"), "token")
629+
h.Equals(t, req.URL.String(), requestPath)
630+
rw.WriteHeader(404)
631+
}))
632+
defer server.Close()
633+
634+
// Use URL from our local test server
635+
imds := ec2metadata.New(server.URL, 1)
636+
637+
_, err := imds.GetMetadataInfo(requestPath, true)
638+
639+
h.Assert(t, err == nil, "Expected error to be nil but it was not")
640+
}
641+
642+
func TestGetMetadataServiceRequest500AllowMissing(t *testing.T) {
643+
var requestPath string = "/latest/meta-data/instance-type"
644+
645+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
646+
rw.Header().Add("X-aws-ec2-metadata-token-ttl-seconds", "100")
647+
if req.URL.String() == "/latest/api/token" {
648+
rw.WriteHeader(200)
649+
_, err := rw.Write([]byte(`token`))
650+
h.Ok(t, err)
651+
return
652+
}
653+
h.Equals(t, req.Header.Get("X-aws-ec2-metadata-token"), "token")
654+
h.Equals(t, req.URL.String(), requestPath)
655+
rw.WriteHeader(500)
656+
}))
657+
defer server.Close()
658+
659+
// Use URL from our local test server
660+
imds := ec2metadata.New(server.URL, 1)
661+
662+
_, err := imds.GetMetadataInfo(requestPath, true)
663+
664+
h.Assert(t, err != nil, "Error expected because request errored with 500")
615665
}
616666

617667
func TestGetMetadataServiceRequestFailure(t *testing.T) {
618668
// Use URL from our local test server
619669
imds := ec2metadata.New("/some-path-that-will-error", 1)
620670

621-
_, err := imds.GetMetadataInfo("/latest/meta-data/instance-type")
671+
_, err := imds.GetMetadataInfo("/latest/meta-data/instance-type", false)
622672
h.Assert(t, err != nil, "Error expected because no server should be running")
623673
}
624674

@@ -643,7 +693,7 @@ func TestGetMetadataServiceSuccess(t *testing.T) {
643693
// Use URL from our local test server
644694
imds := ec2metadata.New(server.URL, 1)
645695

646-
resp, err := imds.GetMetadataInfo(requestPath)
696+
resp, err := imds.GetMetadataInfo(requestPath, false)
647697

648698
h.Ok(t, err)
649699
h.Equals(t, `x1.32xlarge`, resp)

0 commit comments

Comments
 (0)