api_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package ec2metadata_test
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "net/http"
  6. "net/http/httptest"
  7. "path"
  8. "strings"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/aws/aws-sdk-go/aws"
  12. "github.com/aws/aws-sdk-go/aws/awserr"
  13. "github.com/aws/aws-sdk-go/aws/ec2metadata"
  14. "github.com/aws/aws-sdk-go/aws/request"
  15. "github.com/aws/aws-sdk-go/awstesting/unit"
  16. )
  17. const instanceIdentityDocument = `{
  18. "devpayProductCodes" : null,
  19. "availabilityZone" : "us-east-1d",
  20. "privateIp" : "10.158.112.84",
  21. "version" : "2010-08-31",
  22. "region" : "us-east-1",
  23. "instanceId" : "i-1234567890abcdef0",
  24. "billingProducts" : null,
  25. "instanceType" : "t1.micro",
  26. "accountId" : "123456789012",
  27. "pendingTime" : "2015-11-19T16:32:11Z",
  28. "imageId" : "ami-5fb8c835",
  29. "kernelId" : "aki-919dcaf8",
  30. "ramdiskId" : null,
  31. "architecture" : "x86_64"
  32. }`
  33. const validIamInfo = `{
  34. "Code" : "Success",
  35. "LastUpdated" : "2016-03-17T12:27:32Z",
  36. "InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
  37. "InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
  38. }`
  39. const unsuccessfulIamInfo = `{
  40. "Code" : "Failed",
  41. "LastUpdated" : "2016-03-17T12:27:32Z",
  42. "InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
  43. "InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
  44. }`
  45. func initTestServer(path string, resp string) *httptest.Server {
  46. return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  47. if r.RequestURI != path {
  48. http.Error(w, "not found", http.StatusNotFound)
  49. return
  50. }
  51. w.Write([]byte(resp))
  52. }))
  53. }
  54. func TestEndpoint(t *testing.T) {
  55. c := ec2metadata.New(unit.Session)
  56. op := &request.Operation{
  57. Name: "GetMetadata",
  58. HTTPMethod: "GET",
  59. HTTPPath: path.Join("/", "meta-data", "testpath"),
  60. }
  61. req := c.NewRequest(op, nil, nil)
  62. assert.Equal(t, "http://169.254.169.254/latest", req.ClientInfo.Endpoint)
  63. assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String())
  64. }
  65. func TestGetMetadata(t *testing.T) {
  66. server := initTestServer(
  67. "/latest/meta-data/some/path",
  68. "success", // real response includes suffix
  69. )
  70. defer server.Close()
  71. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  72. resp, err := c.GetMetadata("some/path")
  73. assert.NoError(t, err)
  74. assert.Equal(t, "success", resp)
  75. }
  76. func TestGetRegion(t *testing.T) {
  77. server := initTestServer(
  78. "/latest/meta-data/placement/availability-zone",
  79. "us-west-2a", // real response includes suffix
  80. )
  81. defer server.Close()
  82. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  83. region, err := c.Region()
  84. assert.NoError(t, err)
  85. assert.Equal(t, "us-west-2", region)
  86. }
  87. func TestMetadataAvailable(t *testing.T) {
  88. server := initTestServer(
  89. "/latest/meta-data/instance-id",
  90. "instance-id",
  91. )
  92. defer server.Close()
  93. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  94. available := c.Available()
  95. assert.True(t, available)
  96. }
  97. func TestMetadataIAMInfo_success(t *testing.T) {
  98. server := initTestServer(
  99. "/latest/meta-data/iam/info",
  100. validIamInfo,
  101. )
  102. defer server.Close()
  103. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  104. iamInfo, err := c.IAMInfo()
  105. assert.NoError(t, err)
  106. assert.Equal(t, "Success", iamInfo.Code)
  107. assert.Equal(t, "arn:aws:iam::123456789012:instance-profile/my-instance-profile", iamInfo.InstanceProfileArn)
  108. assert.Equal(t, "AIPAABCDEFGHIJKLMN123", iamInfo.InstanceProfileID)
  109. }
  110. func TestMetadataIAMInfo_failure(t *testing.T) {
  111. server := initTestServer(
  112. "/latest/meta-data/iam/info",
  113. unsuccessfulIamInfo,
  114. )
  115. defer server.Close()
  116. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  117. iamInfo, err := c.IAMInfo()
  118. assert.NotNil(t, err)
  119. assert.Equal(t, "", iamInfo.Code)
  120. assert.Equal(t, "", iamInfo.InstanceProfileArn)
  121. assert.Equal(t, "", iamInfo.InstanceProfileID)
  122. }
  123. func TestMetadataNotAvailable(t *testing.T) {
  124. c := ec2metadata.New(unit.Session)
  125. c.Handlers.Send.Clear()
  126. c.Handlers.Send.PushBack(func(r *request.Request) {
  127. r.HTTPResponse = &http.Response{
  128. StatusCode: int(0),
  129. Status: http.StatusText(int(0)),
  130. Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
  131. }
  132. r.Error = awserr.New("RequestError", "send request failed", nil)
  133. r.Retryable = aws.Bool(true) // network errors are retryable
  134. })
  135. available := c.Available()
  136. assert.False(t, available)
  137. }
  138. func TestMetadataErrorResponse(t *testing.T) {
  139. c := ec2metadata.New(unit.Session)
  140. c.Handlers.Send.Clear()
  141. c.Handlers.Send.PushBack(func(r *request.Request) {
  142. r.HTTPResponse = &http.Response{
  143. StatusCode: http.StatusBadRequest,
  144. Status: http.StatusText(http.StatusBadRequest),
  145. Body: ioutil.NopCloser(strings.NewReader("error message text")),
  146. }
  147. r.Retryable = aws.Bool(false) // network errors are retryable
  148. })
  149. data, err := c.GetMetadata("uri/path")
  150. assert.Empty(t, data)
  151. assert.Contains(t, err.Error(), "error message text")
  152. }
  153. func TestEC2RoleProviderInstanceIdentity(t *testing.T) {
  154. server := initTestServer(
  155. "/latest/dynamic/instance-identity/document",
  156. instanceIdentityDocument,
  157. )
  158. defer server.Close()
  159. c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
  160. doc, err := c.GetInstanceIdentityDocument()
  161. assert.Nil(t, err, "Expect no error, %v", err)
  162. assert.Equal(t, doc.AccountID, "123456789012")
  163. assert.Equal(t, doc.AvailabilityZone, "us-east-1d")
  164. assert.Equal(t, doc.Region, "us-east-1")
  165. }