diff --git a/aws/ec2metadata/api.go b/aws/ec2metadata/api.go index 669c813a00d..e5755d11b0b 100644 --- a/aws/ec2metadata/api.go +++ b/aws/ec2metadata/api.go @@ -3,6 +3,7 @@ package ec2metadata import ( "encoding/json" "fmt" + "net/http" "path" "strings" "time" @@ -27,6 +28,27 @@ func (c *EC2Metadata) GetMetadata(p string) (string, error) { return output.Content, req.Send() } +// GetUserData returns the userdata that was configured for the service. If +// there is no user-data setup for the EC2 instance a "NotFoundError" error +// code will be returned. +func (c *EC2Metadata) GetUserData() (string, error) { + op := &request.Operation{ + Name: "GetUserData", + HTTPMethod: "GET", + HTTPPath: path.Join("/", "user-data"), + } + + output := &metadataOutput{} + req := c.NewRequest(op, nil, output) + req.Handlers.UnmarshalError.PushBack(func(r *request.Request) { + if r.HTTPResponse.StatusCode == http.StatusNotFound { + r.Error = awserr.New("NotFoundError", "user-data not found", r.Error) + } + }) + + return output.Content, req.Send() +} + // GetDynamicData uses the path provided to request information from the EC2 // instance metadata service for dynamic data. The content will be returned // as a string, or error if the request failed. diff --git a/aws/ec2metadata/api_test.go b/aws/ec2metadata/api_test.go index be813aae270..35e75782b9b 100644 --- a/aws/ec2metadata/api_test.go +++ b/aws/ec2metadata/api_test.go @@ -2,6 +2,8 @@ package ec2metadata_test import ( "bytes" + "fmt" + "io" "io/ioutil" "net/http" "net/http/httptest" @@ -87,6 +89,51 @@ func TestGetMetadata(t *testing.T) { assert.Equal(t, "success", resp) } +func TestGetUserData(t *testing.T) { + server := initTestServer( + "/latest/user-data", + "success", // real response includes suffix + ) + defer server.Close() + c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}) + + resp, err := c.GetUserData() + + assert.NoError(t, err) + assert.Equal(t, "success", resp) +} + +func TestGetUserData_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reader := strings.NewReader(` + + + + 404 - Not Found + + +

404 - Not Found

+ +`) + w.Header().Set("Content-Type", "text/html") + w.Header().Set("Content-Length", fmt.Sprintf("%d", reader.Len())) + w.WriteHeader(http.StatusNotFound) + io.Copy(w, reader) + })) + + defer server.Close() + c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}) + + resp, err := c.GetUserData() + assert.Error(t, err) + assert.Empty(t, resp) + + aerr, ok := err.(awserr.Error) + assert.True(t, ok) + assert.Equal(t, "NotFoundError", aerr.Code()) +} + func TestGetRegion(t *testing.T) { server := initTestServer( "/latest/meta-data/placement/availability-zone",