diff --git a/mocks/http.go b/mocks/http.go new file mode 100644 index 000000000..5c255dcab --- /dev/null +++ b/mocks/http.go @@ -0,0 +1,19 @@ +package mocks + +import ( + "net/http" + + mock "github.com/stretchr/testify/mock" +) + +// HttpClient is an autogenerated mock type for the Client type +type HttpClient struct { + mock.Mock +} + +// Do provides a mock function +func (_m *HttpClient) Do(req *http.Request) (*http.Response, error) { + ret := _m.Called(req) + + return ret.Get(0).(*http.Response), ret.Error(1) +} diff --git a/pkg/iac/terraform/state/backend/backend.go b/pkg/iac/terraform/state/backend/backend.go index 5d37f2b86..65d5beffc 100644 --- a/pkg/iac/terraform/state/backend/backend.go +++ b/pkg/iac/terraform/state/backend/backend.go @@ -3,6 +3,7 @@ package backend import ( "fmt" "io" + "net/http" "github.com/cloudskiff/driftctl/pkg/iac/config" "github.com/pkg/errors" @@ -46,7 +47,7 @@ func GetBackend(config config.SupplierConfig, opts *Options) (Backend, error) { case BackendKeyHTTP: fallthrough case BackendKeyHTTPS: - return NewHTTPReader(fmt.Sprintf("%s://%s", config.Backend, config.Path), opts) + return NewHTTPReader(&http.Client{}, fmt.Sprintf("%s://%s", config.Backend, config.Path), opts) default: return nil, errors.Errorf("Unsupported backend '%s'", backend) } diff --git a/pkg/iac/terraform/state/backend/http_reader.go b/pkg/iac/terraform/state/backend/http_reader.go index c1a4cc206..3232c8f43 100644 --- a/pkg/iac/terraform/state/backend/http_reader.go +++ b/pkg/iac/terraform/state/backend/http_reader.go @@ -16,7 +16,11 @@ type HTTPBackend struct { reader io.ReadCloser } -func NewHTTPReader(rawURL string, opts *Options) (*HTTPBackend, error) { +type HttpClient interface { + Do(req *http.Request) (*http.Response, error) +} + +func NewHTTPReader(client HttpClient, rawURL string, opts *Options) (*HTTPBackend, error) { req, err := http.NewRequest(http.MethodGet, rawURL, nil) if err != nil { return nil, err @@ -26,7 +30,6 @@ func NewHTTPReader(rawURL string, opts *Options) (*HTTPBackend, error) { req.Header.Add(key, value) } - client := &http.Client{} res, err := client.Do(req) if err != nil { return nil, err diff --git a/pkg/iac/terraform/state/backend/http_reader_test.go b/pkg/iac/terraform/state/backend/http_reader_test.go index a5890c0c4..de5cb1ac2 100644 --- a/pkg/iac/terraform/state/backend/http_reader_test.go +++ b/pkg/iac/terraform/state/backend/http_reader_test.go @@ -3,10 +3,14 @@ package backend import ( "errors" "io" + "net/http" + "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + + "github.com/cloudskiff/driftctl/mocks" ) func TestNewHTTPReader(t *testing.T) { @@ -15,10 +19,10 @@ func TestNewHTTPReader(t *testing.T) { options *Options } tests := []struct { - name string - args args - wantURL string - wantErr error + name string + args args + wantErr error + httpClient func() HttpClient }{ { name: "Should fail with wrong URL", @@ -28,37 +32,70 @@ func TestNewHTTPReader(t *testing.T) { Headers: map[string]string{}, }, }, - wantURL: "", wantErr: errors.New("Get \"wrong_url\": unsupported protocol scheme \"\""), + httpClient: func() HttpClient { + return &http.Client{} + }, }, { name: "Should fetch URL with auth header", args: args{ - url: "https://raw.githubusercontent.com/cloudskiff/driftctl/main/.dockerignore", + url: "https://wrong.url/cloudskiff/driftctl/main/terraform.tfstate", options: &Options{ Headers: map[string]string{ "Authorization": "Basic Test", }, }, }, - wantURL: "https://raw.githubusercontent.com/cloudskiff/driftctl/main/.dockerignore", wantErr: nil, + httpClient: func() HttpClient { + m := &mocks.HttpClient{} + + req, _ := http.NewRequest(http.MethodGet, "https://wrong.url/cloudskiff/driftctl/main/terraform.tfstate", nil) + + req.Header.Add("Authorization", "Basic Test") + + bodyReader := strings.NewReader("test") + bodyReadCloser := io.NopCloser(bodyReader) + + m.On("Do", req).Return(&http.Response{ + StatusCode: 200, + Body: bodyReadCloser, + }, nil) + + return m + }, }, { name: "Should fail with bad status code", args: args{ - url: "https://raw.githubusercontent.com/cloudskiff/driftctl-test/main/.dockerignore", + url: "https://wrong.url/cloudskiff/driftctl/main/terraform.tfstate", options: &Options{ Headers: map[string]string{}, }, }, - wantURL: "https://raw.githubusercontent.com/cloudskiff/driftctl-badprojecturl", - wantErr: errors.New("error in backend HTTP(s): non-200 OK status code: 404 Not Found body: \"404: Not Found\""), + wantErr: errors.New("error in backend HTTP(s): non-200 OK status code: 404 Not Found body: \"test\""), + httpClient: func() HttpClient { + m := &mocks.HttpClient{} + + req, _ := http.NewRequest(http.MethodGet, "https://wrong.url/cloudskiff/driftctl/main/terraform.tfstate", nil) + + bodyReader := strings.NewReader("test") + bodyReadCloser := io.NopCloser(bodyReader) + + m.On("Do", req).Return(&http.Response{ + StatusCode: 404, + Status: "404 Not Found", + Body: bodyReadCloser, + }, nil) + + return m + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewHTTPReader(tt.args.url, tt.args.options) + got, err := NewHTTPReader(tt.httpClient(), tt.args.url, tt.args.options) if tt.wantErr != nil { assert.EqualError(t, err, tt.wantErr.Error()) return @@ -66,7 +103,6 @@ func TestNewHTTPReader(t *testing.T) { assert.NoError(t, err) } assert.NotNil(t, got) - assert.Equal(t, tt.wantURL, got.url) }) } }