diff --git a/Makefile b/Makefile index 1784a00..0643972 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ MAIN_VERSION:=$(shell git describe --always || echo "1.0") VERSION:=${MAIN_VERSION}\#$(shell git log -n 1 --pretty=format:"%h") -PACKAGES:=$(shell go list ./... | sed -n '1!p' | grep -v -e /vendor/ -e github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces) -LDFLAGS:=-ldflags "-X github.com/ch-robinson/vault-elastic-plugin/plugin.Version=${VERSION}" +PACKAGES:=$(shell go list ./... | sed -n '1!p' | grep -v -e /vendor/) +LDFLAGS:=-ldflags "-X github.com/ch-robinson/vault-elastic-plugin/main.Version=${VERSION}" ifeq ($(OS),Windows_NT) DETECTED_OS := Windows @@ -20,14 +20,6 @@ default: test test: @echo "mode: count" > coverage-all.out - @echo - @echo "************** SKIPPING TESTS IN PACKAGES ****************" - @echo - @echo "skipping github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" - @echo - @echo "**********************************************************" - @echo - @$(foreach pkg,$(PACKAGES), \ go test -p=1 -cover -covermode=count -coverprofile=coverage.out ${pkg} || exit 1; \ tail -n +2 coverage.out >> coverage-all.out;) diff --git a/Readme.md b/Readme.md index b3c267c..53a484d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ # vault-elastic-plugin -### Setup +## Setup *** NOTE: For Mac or linux, make should be installed by default so you can skip steps 2 and 3 *** @@ -12,16 +12,16 @@ - Mac - ```brew install glide``` 5. ```go get github.com/ch-robinson/vault-elastic-plugin``` -### Testing locally +## Testing locally 1. Download [Vault](https://www.vaultproject.io/downloads.html) and extract the compressed file to the location of your choosing 2. Add Vault to path 3. In a new terminal run Vault: ```make run-vault``` -4. In a new terminal run: +4. In a new terminal run: - With build and vault DB configuration: ```make test-plugin ELASTIC_BASE_URI= ELASTIC_PASSWORD= ELASTIC_USERNAME= INCLUDE_BUILD=true ENABLE_VAULT_DB=true``` - Without build: ```make test-plugin ELASTIC_BASE_URI= ELASTIC_PASSWORD= ELASTIC_USERNAME= INCLUDE_BUILD=false ENABLE_VAULT_DB=true``` -### Build +## Build - Unix based: ```make build``` - Powershell (if make is not in path): ```C:\Program Files (x86)\GnuWin32\bin\make.exe build``` @@ -29,16 +29,16 @@ The executable binary is located ../bin/run -### Unit Testing +## Unit Testing + +At the root of the project, run -At the root of the project, run - Unix based: ```make test``` - Powershell (if make is not in path): ```C:\Program Files (x86)\GnuWin32\bin\make.exe test``` - bash for Windows (if make is not in path): ```/c/Program\ Files\ \(x86\)/GnuWin32/bin/make.exe test``` -### Dependencies +## Dependencies - Unix based: ```make depends``` - Powershell (if make is not in path): ```C:\Program Files (x86)\GnuWin32\bin\make.exe depends``` - bash for Windows (if make is not in path): ```/c/Program\ Files\ \(x86\)/GnuWin32/bin/make.exe depends``` - diff --git a/plugin/elastic/connection_producer.go b/elastic/connection_producer.go similarity index 91% rename from plugin/elastic/connection_producer.go rename to elastic/connection_producer.go index 8dc0fca..529e2d3 100644 --- a/plugin/elastic/connection_producer.go +++ b/elastic/connection_producer.go @@ -5,7 +5,7 @@ import ( "fmt" "sync" - "github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" + "github.com/ch-robinson/vault-elastic-plugin/httputil" "github.com/mitchellh/mapstructure" ) @@ -17,7 +17,7 @@ type connectionProducer struct { Password string `json:"password" structs:"password" mapstructure:"password"` RawConfig map[string]interface{} Type string - HTTPClient interfaces.IHTTPClient + HTTPClient httputil.ClientWrapperer sync.RWMutex } diff --git a/plugin/elastic/connection_producer_test.go b/elastic/connection_producer_test.go similarity index 100% rename from plugin/elastic/connection_producer_test.go rename to elastic/connection_producer_test.go diff --git a/plugin/elastic/elastic_db.go b/elastic/elastic_db.go similarity index 90% rename from plugin/elastic/elastic_db.go rename to elastic/elastic_db.go index deef9c6..dc048b8 100644 --- a/plugin/elastic/elastic_db.go +++ b/elastic/elastic_db.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - "github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" + "github.com/ch-robinson/vault-elastic-plugin/httputil" "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/builtin/logical/database/dbplugin" "github.com/hashicorp/vault/plugins/helper/database/credsutil" @@ -24,7 +24,7 @@ type Database struct { var _ dbplugin.Database = &Database{} // New returns a new Elastic instance with provided implementation of http.Client -func New(httpClient interfaces.IHTTPClient) (interface{}, error) { +func New(httpClient httputil.ClientWrapperer) (interface{}, error) { // setup struct db := &Database{ connectionProducer: &connectionProducer{ @@ -47,7 +47,7 @@ func New(httpClient interfaces.IHTTPClient) (interface{}, error) { } // Run instantiates the Database struct, and runs the RPC server for the plugin -func Run(serve func(plugin interface{}, tlsConfig *api.TLSConfig), apiTLSConfig *api.TLSConfig, httpClient interfaces.IHTTPClient) error { +func Run(serve func(plugin interface{}, tlsConfig *api.TLSConfig), apiTLSConfig *api.TLSConfig, httpClient httputil.ClientWrapperer) error { dbType, err := New(httpClient) if err != nil { @@ -155,7 +155,7 @@ func (m *Database) RevokeUser(ctx context.Context, statements dbplugin.Statement // RotateRootCredentials rotates the root superuser credentials stored for the database connection func (m *Database) RotateRootCredentials(ctx context.Context, statements []string) (map[string]interface{}, error) { if len(m.Username) == 0 || len(m.Password) == 0 { - return nil, errors.New("Both the username and password are required.") + return nil, errors.New("both the username and password are required") } password, err := m.GeneratePassword() diff --git a/plugin/elastic/elastic_db_test.go b/elastic/elastic_db_test.go similarity index 94% rename from plugin/elastic/elastic_db_test.go rename to elastic/elastic_db_test.go index 390bc3b..510a36a 100644 --- a/plugin/elastic/elastic_db_test.go +++ b/elastic/elastic_db_test.go @@ -256,7 +256,7 @@ func TestRotateRootCredentialsFailWithoutConnectionCredentials(t *testing.T) { _, err := db.RotateRootCredentials(testdata.NewMockVaultContext(), []string{}) - assert.Equal(t, "Both the username and password are required.", err.Error()) + assert.Equal(t, "both the username and password are required", err.Error()) } func TestRotateRootCredentialsFailOnBadUsername(t *testing.T) { diff --git a/httputil/http_client.go b/httputil/http_client.go new file mode 100644 index 0000000..8fb89fa --- /dev/null +++ b/httputil/http_client.go @@ -0,0 +1,108 @@ +package httputil + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" +) + +// HTTP is the interface for http.Client +// https://golang.org/pkg/net/http/ +type httpWrapper interface { + // Do wraps the http.Client Do function + Do(req *http.Request) (*http.Response, error) +} + +// ClientWrapperer is the interface for functions relating to building http request +type ClientWrapperer interface { + // Do peforms an http request. This is just a wrapper for the http.Client function + // calls HTTP.Do for ease of testing + Do(req *http.Request) (*http.Response, error) + // BuildBasicAuthRequest creates an http.Request with basic authoriztion header. + // body must be map[string]interface{} + BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) + // ReadHTTPResponse returns the response body as map[string]interface{} + ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) +} + +// ClientWrapper is the wrapper for interacting with http methods +type ClientWrapper struct { + client httpWrapper +} + +// New instantiates a new ClientWrapper +func New(client httpWrapper) *ClientWrapper { + return &ClientWrapper{client} +} + +// Do peforms an http request +func (c *ClientWrapper) Do(req *http.Request) (*http.Response, error) { + return c.client.Do(req) +} + +// BuildBasicAuthRequest creates an http.Request with basic authoriztion header. +// body must be map[string]interface{} +func (c *ClientWrapper) BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) { + var req *http.Request + var err error + + if body != nil && len(body) > 0 { + reqBody, err := json.Marshal(body) + if err != nil { + return nil, err + } + + recloser := NewClosingBuffer(bytes.NewBuffer(reqBody)).GetReadCloser().(*ClosingBuffer) + + if err != nil { + return nil, err + } + + req, err = http.NewRequest(httpMethod, requestURL, recloser) + } else { + req, err = http.NewRequest(httpMethod, requestURL, nil) + } + + req.SetBasicAuth(username, password) + + if err != nil { + return nil, err + } + + c.addHeaders(&req.Header) + + return req, nil +} + +// ReadHTTPResponse returns the response body as map[string]interface{} +func (c *ClientWrapper) ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) { + resBody, err := ioutil.ReadAll(res.Body) + + defer res.Body.Close() + + if err != nil { + return nil, err + } + + var body map[string]interface{} + + err = json.Unmarshal(resBody, &body) + + if err != nil { + return nil, err + } + + // Throw error if not ok. Might need to watch out for other success codes, but this should be ok. + if res.StatusCode != 200 { + return nil, err + } + + return body, nil +} + +// addHeaders adds http.Headers. If accessToken is provided, an Authorization header will be added with given authType (Bearer, token, etc.) +func (c *ClientWrapper) addHeaders(header *http.Header) { + header.Add("Content-Type", "application/json") + header.Add("Accept", "application/json") +} diff --git a/plugin/util/http_client_test.go b/httputil/http_client_test.go similarity index 60% rename from plugin/util/http_client_test.go rename to httputil/http_client_test.go index 670ebe6..fcb318e 100644 --- a/plugin/util/http_client_test.go +++ b/httputil/http_client_test.go @@ -1,4 +1,4 @@ -package util +package httputil import ( "bytes" @@ -9,22 +9,22 @@ import ( "github.com/stretchr/testify/assert" ) -func initHTTPClient(resBody *string) *HTTPClient { +func initClient(resBody *string) *ClientWrapper { mockHTTP := testdata.NewMockHTTP(resBody) - httpClient := NewHTTPClient(mockHTTP) - return httpClient + clientWrapper := New(mockHTTP) + return clientWrapper } -func TestNewHTTPClient(t *testing.T) { +func TestNewClient(t *testing.T) { mockHTTP := testdata.NewMockHTTP(nil) - httpClient := NewHTTPClient(mockHTTP) + clientWrapper := New(mockHTTP) - assert.Equal(t, mockHTTP, httpClient.client) + assert.Equal(t, mockHTTP, clientWrapper.client) } func TestReadHTTPResponse(t *testing.T) { - httpClient := initHTTPClient(nil) + clientWrapper := initClient(nil) readCloser := NewClosingBuffer(bytes.NewBufferString("{\"test\":\"body\"}")).GetReadCloser() @@ -34,17 +34,17 @@ func TestReadHTTPResponse(t *testing.T) { Body: readCloser, } - response, err := httpClient.ReadHTTPResponse(res) + response, err := clientWrapper.ReadHTTPResponse(res) assert.Nil(t, err) assert.True(t, response != nil) } func TestAddHeaders(t *testing.T) { - httpClient := initHTTPClient(nil) + clientWrapper := initClient(nil) var h http.Header = make(map[string][]string) - httpClient.addHeaders(&h) + clientWrapper.addHeaders(&h) assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, "application/json", h.Get("Accept")) @@ -52,21 +52,21 @@ func TestAddHeaders(t *testing.T) { func TestDo(t *testing.T) { b := "good" - httpClient := initHTTPClient(&b) + clientWrapper := initClient(&b) req, _ := http.NewRequest("GET", "mocked", nil) - _, err := httpClient.Do(req) + _, err := clientWrapper.Do(req) assert.Nil(t, err) } func TestBuildBasicAuthRequestWithBody(t *testing.T) { - httpClient := initHTTPClient(nil) + clientWrapper := initClient(nil) body := make(map[string]interface{}) body["test"] = true - req, err := httpClient.BuildBasicAuthRequest("http://test", "testuser", "testpassword", "POST", body) + req, err := clientWrapper.BuildBasicAuthRequest("http://test", "testuser", "testpassword", "POST", body) assert.Nil(t, err) assert.NotNil(t, req) @@ -74,9 +74,9 @@ func TestBuildBasicAuthRequestWithBody(t *testing.T) { } func TestBuildBasicAuthRequestNilBody(t *testing.T) { - httpClient := initHTTPClient(nil) + clientWrapper := initClient(nil) - req, err := httpClient.BuildBasicAuthRequest("http://test", "testuser", "testpassword", "DELETE", nil) + req, err := clientWrapper.BuildBasicAuthRequest("http://test", "testuser", "testpassword", "DELETE", nil) assert.Nil(t, err) assert.NotNil(t, req) diff --git a/plugin/util/read_closer.go b/httputil/read_closer.go similarity index 92% rename from plugin/util/read_closer.go rename to httputil/read_closer.go index d605137..0deaa15 100644 --- a/plugin/util/read_closer.go +++ b/httputil/read_closer.go @@ -1,4 +1,4 @@ -package util +package httputil import ( "bytes" diff --git a/plugin/util/read_closer_test.go b/httputil/read_closer_test.go similarity index 86% rename from plugin/util/read_closer_test.go rename to httputil/read_closer_test.go index 8340023..1c9c88c 100644 --- a/plugin/util/read_closer_test.go +++ b/httputil/read_closer_test.go @@ -1,4 +1,4 @@ -package util +package httputil import ( "bytes" diff --git a/main.go b/main.go index 53f99ce..883b7bd 100644 --- a/main.go +++ b/main.go @@ -5,18 +5,20 @@ import ( "net/http" "os" - "github.com/ch-robinson/vault-elastic-plugin/plugin/elastic" - "github.com/ch-robinson/vault-elastic-plugin/plugin/util" + "github.com/ch-robinson/vault-elastic-plugin/elastic" + "github.com/ch-robinson/vault-elastic-plugin/httputil" "github.com/hashicorp/vault/helper/pluginutil" "github.com/hashicorp/vault/plugins" ) +var Version = "1.0" + func main() { apiClientMeta := &pluginutil.APIClientMeta{} flags := apiClientMeta.FlagSet() flags.Parse(os.Args[1:]) - clientWrapper := util.NewHTTPClient(&http.Client{}) + clientWrapper := httputil.New(&http.Client{}) if err := elastic.Run(plugins.Serve, apiClientMeta.GetTLSConfig(), clientWrapper); err != nil { log.Println(err) diff --git a/plugin/interfaces/http.go b/plugin/interfaces/http.go deleted file mode 100644 index 7bd1a08..0000000 --- a/plugin/interfaces/http.go +++ /dev/null @@ -1,22 +0,0 @@ -package interfaces - -import "net/http" - -// IHTTP is the interface for http.Client -// https://golang.org/pkg/net/http/ -type IHTTP interface { - // Do wraps the http.Client Do function - Do(req *http.Request) (*http.Response, error) -} - -// IHTTPClient is the interface for functions relating to building http request -type IHTTPClient interface { - // Do peforms an http request. This is just a wrapper for the http.Client function - // calls IHTTP.Do for ease of testing - Do(req *http.Request) (*http.Response, error) - // BuildBasicAuthRequest creates an http.Request with basic authoriztion header. - // body must be map[string]interface{} - BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) - // ReadHTTPResponse returns the response body as map[string]interface{} - ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) -} diff --git a/plugin/util/http_client.go b/plugin/util/http_client.go deleted file mode 100644 index 0dbab86..0000000 --- a/plugin/util/http_client.go +++ /dev/null @@ -1,91 +0,0 @@ -package util - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" -) - -// HTTPClient is the wrapper for interacting with http methods -type HTTPClient struct { - client interfaces.IHTTP -} - -// NewHTTPClient instantiates a new HttpClient -func NewHTTPClient(client interfaces.IHTTP) *HTTPClient { - return &HTTPClient{client} -} - -// Do peforms an http request -func (c *HTTPClient) Do(req *http.Request) (*http.Response, error) { - return c.client.Do(req) -} - -// BuildBasicAuthRequest creates an http.Request with basic authoriztion header. -// body must be map[string]interface{} -func (c *HTTPClient) BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) { - var req *http.Request - var err error - - if body != nil && len(body) > 0 { - reqBody, err := json.Marshal(body) - if err != nil { - return nil, err - } - - recloser := NewClosingBuffer(bytes.NewBuffer(reqBody)).GetReadCloser().(*ClosingBuffer) - - if err != nil { - return nil, err - } - - req, err = http.NewRequest(httpMethod, requestURL, recloser) - } else { - req, err = http.NewRequest(httpMethod, requestURL, nil) - } - - req.SetBasicAuth(username, password) - - if err != nil { - return nil, err - } - - c.addHeaders(&req.Header) - - return req, nil -} - -// ReadHTTPResponse returns the response body as map[string]interface{} -func (c *HTTPClient) ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) { - resBody, err := ioutil.ReadAll(res.Body) - - defer res.Body.Close() - - if err != nil { - return nil, err - } - - var body map[string]interface{} - - err = json.Unmarshal(resBody, &body) - - if err != nil { - return nil, err - } - - // Throw error if not ok. Might need to watch out for other success codes, but this should be ok. - if res.StatusCode != 200 { - return nil, err - } - - return body, nil -} - -// addHeaders adds http.Headers. If accessToken is provided, an Authorization header will be added with given authType (Bearer, token, etc.) -func (c *HTTPClient) addHeaders(header *http.Header) { - header.Add("Content-Type", "application/json") - header.Add("Accept", "application/json") -} diff --git a/plugin/version.go b/plugin/version.go deleted file mode 100644 index 1dae4de..0000000 --- a/plugin/version.go +++ /dev/null @@ -1,6 +0,0 @@ -package plugin - -// Version specifies the current version of the application. -// The value of this variable is replaced with the latest git tag -// by "make" while building or running the application. -var Version = "1.0" diff --git a/testdata/mock_http.go b/testdata/mock_http.go deleted file mode 100644 index 0930217..0000000 --- a/testdata/mock_http.go +++ /dev/null @@ -1,34 +0,0 @@ -package testdata - -import ( - "bytes" - "errors" - "net/http" - - "github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" -) - -// MockHTTP Mock object for http methods -type MockHTTP struct { - responseBody *string -} - -// NewMockHTTP instantiates a new MockHTTP -func NewMockHTTP(responseBody *string) interfaces.IHTTP { - return &MockHTTP{responseBody} -} - -// Do Mock Do request -func (m *MockHTTP) Do(req *http.Request) (*http.Response, error) { - if req == nil { - return nil, errors.New("http post test error") - } - - readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() - - return &http.Response{ - Status: "success", - StatusCode: 200, - Body: readCloser, - }, nil -} diff --git a/testdata/mock_http_client.go b/testdata/mock_http_client.go index 9aed704..0472cd6 100644 --- a/testdata/mock_http_client.go +++ b/testdata/mock_http_client.go @@ -1,99 +1,122 @@ -package testdata - -import ( - "bytes" - "encoding/gob" - "encoding/json" - "errors" - "net/http" - "strings" - - "github.com/ch-robinson/vault-elastic-plugin/plugin/interfaces" -) - -// MockHTTPClient mocks HTTPClient -type MockHTTPClient struct { - responseBody *string - client interfaces.IHTTP -} - -// NewMockHTTPClient instantiates a new mock http client -func NewMockHTTPClient(responseBody *string, client interfaces.IHTTP) interfaces.IHTTPClient { - return &MockHTTPClient{responseBody, client} -} - -// BuildPostBasicAuthRequest mocks building a post request with basic auth -func (m *MockHTTPClient) BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) { - if strings.Contains(requestURL, "bad") { - return nil, errors.New("bad request url") - } else if strings.Contains(requestURL, "nouser") { - return nil, errors.New("user doesn't exist") - } else if strings.Contains(requestURL, "failedbutcontinue") { - return nil, nil - } - - var req *http.Request - var err error - - if body != nil && len(body) > 0 { - var buf bytes.Buffer - - enc := gob.NewEncoder(&buf) - - gob.Register(map[string]interface{}{}) - gob.Register([]interface{}{}) - - err = enc.Encode(body) - - if err != nil { - panic(err) - } - - readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() - - if err != nil { - panic(err) - } - - req, err = http.NewRequest(httpMethod, requestURL, readCloser) - } else { - req, err = http.NewRequest(httpMethod, requestURL, nil) - } - - if err != nil { - panic(err) - } - - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Accept", "application/json") - - return req, nil -} - -// Do mocks a request -func (m *MockHTTPClient) Do(req *http.Request) (resp *http.Response, err error) { - if req == nil { - return nil, errors.New("http post test error") - } - - readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() - - return &http.Response{ - Status: "success", - StatusCode: 200, - Body: readCloser, - }, nil -} - -// ReadHTTPResponse mocks ReadHTTPResponse -func (m *MockHTTPClient) ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) { - var mockRes map[string]interface{} - - err := json.Unmarshal([]byte(*m.responseBody), &mockRes) - - if err != nil { - panic(err) - } - - return mockRes, nil -} +package testdata + +import ( + "bytes" + "encoding/gob" + "encoding/json" + "errors" + "net/http" + "strings" +) + +// MockHTTP Mock object for http methods +type MockHTTP struct { + responseBody *string +} + +// NewMockHTTP instantiates a new MockHTTP +func NewMockHTTP(responseBody *string) *MockHTTP { + return &MockHTTP{responseBody} +} + +// Do Mock Do request +func (m *MockHTTP) Do(req *http.Request) (*http.Response, error) { + if req == nil { + return nil, errors.New("http post test error") + } + + readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() + + return &http.Response{ + Status: "success", + StatusCode: 200, + Body: readCloser, + }, nil +} + +// MockHTTPClient mocks HTTPClient +type MockHTTPClient struct { + responseBody *string + client *MockHTTP +} + +// NewMockHTTPClient instantiates a new mock http client +func NewMockHTTPClient(responseBody *string, client *MockHTTP) *MockHTTPClient { + return &MockHTTPClient{responseBody, client} +} + +// BuildPostBasicAuthRequest mocks building a post request with basic auth +func (m *MockHTTPClient) BuildBasicAuthRequest(requestURL, username, password, httpMethod string, body map[string]interface{}) (*http.Request, error) { + if strings.Contains(requestURL, "bad") { + return nil, errors.New("bad request url") + } else if strings.Contains(requestURL, "nouser") { + return nil, errors.New("user doesn't exist") + } else if strings.Contains(requestURL, "failedbutcontinue") { + return nil, nil + } + + var req *http.Request + var err error + + if body != nil && len(body) > 0 { + var buf bytes.Buffer + + enc := gob.NewEncoder(&buf) + + gob.Register(map[string]interface{}{}) + gob.Register([]interface{}{}) + + err = enc.Encode(body) + + if err != nil { + panic(err) + } + + readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() + + if err != nil { + panic(err) + } + + req, err = http.NewRequest(httpMethod, requestURL, readCloser) + } else { + req, err = http.NewRequest(httpMethod, requestURL, nil) + } + + if err != nil { + panic(err) + } + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + + return req, nil +} + +// Do mocks a request +func (m *MockHTTPClient) Do(req *http.Request) (resp *http.Response, err error) { + if req == nil { + return nil, errors.New("http post test error") + } + + readCloser := newClosingBuffer(bytes.NewBufferString(*m.responseBody)).GetReadCloser() + + return &http.Response{ + Status: "success", + StatusCode: 200, + Body: readCloser, + }, nil +} + +// ReadHTTPResponse mocks ReadHTTPResponse +func (m *MockHTTPClient) ReadHTTPResponse(res *http.Response) (map[string]interface{}, error) { + var mockRes map[string]interface{} + + err := json.Unmarshal([]byte(*m.responseBody), &mockRes) + + if err != nil { + panic(err) + } + + return mockRes, nil +} diff --git a/testdata/read_closer_internal.go b/testdata/mock_read_closer.go similarity index 95% rename from testdata/read_closer_internal.go rename to testdata/mock_read_closer.go index eb7cada..3d51266 100644 --- a/testdata/read_closer_internal.go +++ b/testdata/mock_read_closer.go @@ -1,26 +1,26 @@ -package testdata - -import ( - "bytes" - "io" -) - -type closingBuffer struct { - *bytes.Buffer -} - -// NewClosingBuffer instantiates a new ClosingBuffer -func newClosingBuffer(buf *bytes.Buffer) *closingBuffer { - return &closingBuffer{buf} -} - -// Close returns nil. This is just needed when reading bytes -// and can dispose when called from -func (cb *closingBuffer) Close() error { - return nil -} - -// GetReadCloser returns ClosingBuffer after the buffer is set -func (cb *closingBuffer) GetReadCloser() io.ReadCloser { - return cb -} +package testdata + +import ( + "bytes" + "io" +) + +type closingBuffer struct { + *bytes.Buffer +} + +// NewClosingBuffer instantiates a new ClosingBuffer +func newClosingBuffer(buf *bytes.Buffer) *closingBuffer { + return &closingBuffer{buf} +} + +// Close returns nil. This is just needed when reading bytes +// and can dispose when called from +func (cb *closingBuffer) Close() error { + return nil +} + +// GetReadCloser returns ClosingBuffer after the buffer is set +func (cb *closingBuffer) GetReadCloser() io.ReadCloser { + return cb +} diff --git a/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api.go b/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api.go index 16f87c5..3874684 100644 --- a/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api.go +++ b/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api.go @@ -56,7 +56,7 @@ var ( apiContentTypeValue = []string{"application/octet-stream"} logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count") - apiHTTPClient = &http.Client{ + apHTTPClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: limitDial, @@ -393,7 +393,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) hreq.Header.Set(traceHeader, info) } - tr := apiHTTPClient.Transport.(*http.Transport) + tr := apHTTPClient.Transport.(*http.Transport) var timedOut int32 // atomic; set to 1 if timed out t := time.AfterFunc(timeout, func() { @@ -408,7 +408,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) } }() - hresp, err := apiHTTPClient.Do(hreq) + hresp, err := apHTTPClient.Do(hreq) if err != nil { return nil, &CallError{ Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), diff --git a/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api_pre17.go b/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api_pre17.go index 028b4f0..51dfebd 100644 --- a/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api_pre17.go +++ b/vendor/github.com/hashicorp/vault/vendor/google.golang.org/appengine/internal/api_pre17.go @@ -56,7 +56,7 @@ var ( apiContentTypeValue = []string{"application/octet-stream"} logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count") - apiHTTPClient = &http.Client{ + apHTTPClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: limitDial, @@ -415,7 +415,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) hreq.Header.Set(traceHeader, info) } - tr := apiHTTPClient.Transport.(*http.Transport) + tr := apHTTPClient.Transport.(*http.Transport) var timedOut int32 // atomic; set to 1 if timed out t := time.AfterFunc(timeout, func() { @@ -430,7 +430,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) } }() - hresp, err := apiHTTPClient.Do(hreq) + hresp, err := apHTTPClient.Do(hreq) if err != nil { return nil, &CallError{ Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), diff --git a/vendor/golang.org/x/net/http/httpproxy/proxy.go b/vendor/golang.org/x/net/http/httpproxy/proxy.go index cbe1d2a..453e470 100644 --- a/vendor/golang.org/x/net/http/httpproxy/proxy.go +++ b/vendor/golang.org/x/net/http/httpproxy/proxy.go @@ -51,7 +51,7 @@ type Config struct { // presence of a REQUEST_METHOD environment variable). // When this is set, ProxyForURL will return an error // when HTTPProxy applies, because a client could be - // setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy. + // setting HTTP_PROXY maliciously. See https://golang.org/s/cgHTTPproxy. CGI bool } @@ -106,7 +106,7 @@ func (cfg *Config) proxyForURL(reqURL *url.URL) (*url.URL, error) { if proxy == "" { proxy = cfg.HTTPProxy if proxy != "" && cfg.CGI { - return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy") + return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgHTTPproxy") } } if proxy == "" { diff --git a/vendor/golang.org/x/net/http/httpproxy/proxy_test.go b/vendor/golang.org/x/net/http/httpproxy/proxy_test.go index e4af199..6f6159e 100644 --- a/vendor/golang.org/x/net/http/httpproxy/proxy_test.go +++ b/vendor/golang.org/x/net/http/httpproxy/proxy_test.go @@ -119,7 +119,7 @@ var proxyForURLTests = []proxyForURLTest{{ CGI: true, }, want: "", - wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"), + wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgHTTPproxy"), }, { // HTTPS proxy is still used even in CGI environment. // (perhaps dubious but it's the historical behaviour).