diff --git a/aws/metadata.go b/aws/metadata.go new file mode 100644 index 00000000..3c302dae --- /dev/null +++ b/aws/metadata.go @@ -0,0 +1,46 @@ +package aws + +import ( + "fmt" + "io/ioutil" + "net/http" +) + +type MetadataClient struct { + client *http.Client + URL string +} + +func NewMetadataClient() *MetadataClient { + return &MetadataClient{ + client: &http.Client{}, + URL: `http://169.254.169.254/`, + } +} + +func (m *MetadataClient) LocalIPv4() (string, error) { + return m.get("/latest/meta-data/local-ipv4") +} + +func (m *MetadataClient) PublicIPv4() (string, error) { + return m.get("/latest/meta-data/public-ipv4") +} + +func (m *MetadataClient) get(path string) (string, error) { + resp, err := m.client.Get(m.URL + path) + if err != nil { + return "", err + } + + defer resp.Body.Close() + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("failed to request %s, got: %s", path, resp.Status) + } + return string(b), nil +} diff --git a/aws/metadata_test.go b/aws/metadata_test.go new file mode 100644 index 00000000..f923c461 --- /dev/null +++ b/aws/metadata_test.go @@ -0,0 +1,89 @@ +package aws + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" +) + +func Test_NewMetadataClient(t *testing.T) { + c := NewMetadataClient() + if c == nil { + t.Fatalf("failed to create new Metadata client") + } +} + +func Test_MetadataClient_LocalIPv4(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Fatalf("Client did not use GET") + } + if r.URL.String() != "/latest/meta-data/local-ipv4" { + t.Fatalf("Request URL is wrong, got: %s", r.URL.String()) + } + fmt.Fprint(w, "172.31.34.179") + })) + defer ts.Close() + + c := NewMetadataClient() + c.URL = ts.URL + addr, err := c.LocalIPv4() + if err != nil { + t.Fatalf("failed to get local IPv4 address: %s", err.Error()) + } + if addr != "172.31.34.179" { + t.Fatalf("got incorrect local IPv4 address: %s", addr) + } +} + +func Test_MetadataClient_LocalIPv4Fail(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + })) + defer ts.Close() + + c := NewMetadataClient() + c.URL = ts.URL + _, err := c.LocalIPv4() + if err == nil { + t.Fatalf("failed to get error when server returned 400") + } +} + +func Test_MetadataClient_PublicIPv4(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Fatalf("Client did not use GET") + } + if r.URL.String() != "/latest/meta-data/public-ipv4" { + t.Fatalf("Request URL is wrong, got: %s", r.URL.String()) + } + fmt.Fprint(w, "52.38.41.98") + })) + defer ts.Close() + + c := NewMetadataClient() + c.URL = ts.URL + addr, err := c.PublicIPv4() + if err != nil { + t.Fatalf("failed to get local IPv4 address: %s", err.Error()) + } + if addr != "52.38.41.98" { + t.Fatalf("got incorrect local IPv4 address: %s", addr) + } +} + +func Test_MetadataClient_PublicIPv4Fail(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + })) + defer ts.Close() + + c := NewMetadataClient() + c.URL = ts.URL + _, err := c.PublicIPv4() + if err == nil { + t.Fatalf("failed to get error when server returned 400") + } +}