From 866e7f880c8b4b661979dc9301b12652a406edb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20L=C3=B3pez=20de=20la=20Franca=20Beltran?= Date: Fri, 24 Nov 2023 20:24:13 +0100 Subject: [PATCH] Replace spf13/afero with io/fs --- go.mod | 2 - go.sum | 13 ---- internal/app/cmd/cmd.go | 8 ++- internal/server/http/imposter.go | 30 +++++---- internal/server/http/imposter_test.go | 20 ++++++ internal/server/http/server.go | 38 +++++------ internal/server/http/server_test.go | 66 +++++++++++-------- .../create_gopher.imp.json | 0 8 files changed, 97 insertions(+), 80 deletions(-) create mode 100644 internal/server/http/imposter_test.go rename internal/server/http/test/testdata/{malformatted_imposters => malformed_imposters}/create_gopher.imp.json (100%) diff --git a/go.mod b/go.mod index 8a691e2..c07c96a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.1 github.com/radovskyb/watcher v1.0.7 - github.com/spf13/afero v1.6.0 github.com/spf13/cobra v1.0.0 github.com/stretchr/testify v1.8.4 github.com/xeipuuv/gojsonschema v1.2.0 @@ -21,7 +20,6 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - golang.org/x/text v0.3.8 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1fa10d7..b13bd02 100644 --- a/go.sum +++ b/go.sum @@ -52,7 +52,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -67,8 +66,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -89,8 +86,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -103,7 +98,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -123,14 +117,12 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -141,14 +133,9 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index ac41447..4ddbe0b 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -14,7 +14,6 @@ import ( "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/radovskyb/watcher" - "github.com/spf13/afero" "github.com/spf13/cobra" ) @@ -125,9 +124,12 @@ func runServer(cfg killgrave.Config) server.Server { log.Fatal(err) } - imposterFs := server.NewImposterFS(afero.NewOsFs()) + imposterFs, err := server.NewImposterFS(cfg.ImpostersPath) + if err != nil { + log.Fatal(err) + } + s := server.NewServer( - cfg.ImpostersPath, router, &httpServer, proxyServer, diff --git a/internal/server/http/imposter.go b/internal/server/http/imposter.go index 0d4e831..bfd99b5 100644 --- a/internal/server/http/imposter.go +++ b/internal/server/http/imposter.go @@ -3,14 +3,13 @@ package http import ( "encoding/json" "fmt" - "io/ioutil" + "io/fs" "os" "path" "path/filepath" "strings" "time" - "github.com/spf13/afero" "gopkg.in/yaml.v2" ) @@ -73,17 +72,24 @@ type Response struct { } type ImposterFs struct { - fs afero.Fs + path string + fs fs.FS } -func NewImposterFS(fs afero.Fs) ImposterFs { - return ImposterFs{ - fs: fs, +func NewImposterFS(path string) (ImposterFs, error) { + // TODO: What if user lacks permissions? + if _, err := os.Stat(path); os.IsNotExist(err) { + return ImposterFs{}, fmt.Errorf("%w: the directory %s doesn't exists", err, path) } + + return ImposterFs{ + path: path, + fs: os.DirFS(path), + }, nil } -func (i ImposterFs) FindImposters(impostersDirectory string, impostersCh chan []Imposter) error { - err := afero.Walk(i.fs, impostersDirectory, func(path string, info os.FileInfo, err error) error { +func (i ImposterFs) FindImposters(impostersCh chan []Imposter) error { + err := fs.WalkDir(i.fs, ".", func(path string, info fs.DirEntry, err error) error { if err != nil { return fmt.Errorf("%w: error finding imposters", err) } @@ -111,10 +117,8 @@ func (i ImposterFs) FindImposters(impostersDirectory string, impostersCh chan [] } func (i ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposter, error) { - imposterFile, _ := i.fs.Open(imposterConfig.FilePath) - defer imposterFile.Close() - - bytes, _ := ioutil.ReadAll(imposterFile) + // TODO: Error handling? + bytes, _ := fs.ReadFile(i.fs, imposterConfig.FilePath) var parseError error var imposters []Imposter @@ -132,7 +136,7 @@ func (i ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposte return nil, fmt.Errorf("%w: error while unmarshalling imposter's file %s", parseError, imposterConfig.FilePath) } - for i, _ := range imposters { + for i := range imposters { imposters[i].BasePath = filepath.Dir(imposterConfig.FilePath) imposters[i].Path = imposterConfig.FilePath } diff --git a/internal/server/http/imposter_test.go b/internal/server/http/imposter_test.go new file mode 100644 index 0000000..4e8f3d9 --- /dev/null +++ b/internal/server/http/imposter_test.go @@ -0,0 +1,20 @@ +package http + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewImposterFS(t *testing.T) { + t.Run("imposters directory not found", func(t *testing.T) { + _, err := NewImposterFS("failImposterPath") + assert.Error(t, err) + assert.Contains(t, err.Error(), "the directory failImposterPath doesn't exists") + }) + + t.Run("existing imposters directory", func(t *testing.T) { + _, err := NewImposterFS("test/testdata/imposters") + assert.NoError(t, err) + }) +} diff --git a/internal/server/http/server.go b/internal/server/http/server.go index f34d438..e3e96a6 100644 --- a/internal/server/http/server.go +++ b/internal/server/http/server.go @@ -4,14 +4,11 @@ import ( "context" "crypto/tls" _ "embed" - "fmt" - "log" - "net/http" - "os" - killgrave "github.com/friendsofgo/killgrave/internal" "github.com/gorilla/handlers" "github.com/gorilla/mux" + "log" + "net/http" ) //go:embed cert/server.key @@ -31,23 +28,21 @@ type ServerOpt func(s *Server) // Server definition of mock server type Server struct { - impostersPath string - router *mux.Router - httpServer *http.Server - proxy *Proxy - secure bool - imposterFs ImposterFs + router *mux.Router + httpServer *http.Server + proxy *Proxy + secure bool + imposterFs ImposterFs } // NewServer initialize the mock server -func NewServer(p string, r *mux.Router, httpServer *http.Server, proxyServer *Proxy, secure bool, fs ImposterFs) Server { +func NewServer(r *mux.Router, httpServer *http.Server, proxyServer *Proxy, secure bool, fs ImposterFs) Server { return Server{ - impostersPath: p, - router: r, - httpServer: httpServer, - proxy: proxyServer, - secure: secure, - imposterFs: fs, + router: r, + httpServer: httpServer, + proxy: proxyServer, + secure: secure, + imposterFs: fs, } } @@ -89,14 +84,11 @@ func (s *Server) Build() error { return nil } - if _, err := os.Stat(s.impostersPath); os.IsNotExist(err) { - return fmt.Errorf("%w: the directory %s doesn't exists", err, s.impostersPath) - } var impostersCh = make(chan []Imposter) var done = make(chan struct{}) go func() { - s.imposterFs.FindImposters(s.impostersPath, impostersCh) + s.imposterFs.FindImposters(impostersCh) done <- struct{}{} }() loop: @@ -117,7 +109,7 @@ loop: return nil } -// Run run launch a previous configured http server if any error happens while the starting process +// Run launch a previous configured http server if any error happens while the starting process // application will be crashed func (s *Server) Run() { go func() { diff --git a/internal/server/http/server_test.go b/internal/server/http/server_test.go index e083af5..42c2d4b 100644 --- a/internal/server/http/server_test.go +++ b/internal/server/http/server_test.go @@ -2,7 +2,6 @@ package http import ( "crypto/tls" - "errors" "io" "io/ioutil" "log" @@ -14,8 +13,8 @@ import ( killgrave "github.com/friendsofgo/killgrave/internal" "github.com/gorilla/mux" - "github.com/spf13/afero" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMain(m *testing.M) { @@ -24,26 +23,30 @@ func TestMain(m *testing.M) { } func TestServer_Build(t *testing.T) { - imposterFs := NewImposterFS(afero.NewOsFs()) + newServer := func(fs ImposterFs) Server { + return NewServer(mux.NewRouter(), &http.Server{}, &Proxy{}, false, fs) + } - var serverData = []struct { - name string - server Server - err error + testCases := map[string]struct { + impostersPath string + shouldFail bool }{ - {"imposter directory not found", NewServer("failImposterPath", nil, &http.Server{}, &Proxy{}, false, imposterFs), errors.New("hello")}, - {"malformatted json", NewServer("test/testdata/malformatted_imposters", nil, &http.Server{}, &Proxy{}, false, imposterFs), nil}, - {"valid imposter", NewServer("test/testdata/imposters", mux.NewRouter(), &http.Server{}, &Proxy{}, false, imposterFs), nil}, + "imposters with malformed json": {impostersPath: "test/testdata/malformed_imposters"}, + "valid imposters": {impostersPath: "test/testdata/imposters"}, } - for _, tt := range serverData { - t.Run(tt.name, func(t *testing.T) { - err := tt.server.Build() + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + fs, err := NewImposterFS(tc.impostersPath) + require.NoError(t, err) + + srv := newServer(fs) + err = srv.Build() - if tt.err != nil { - assert.NotNil(t, err) + if tc.shouldFail { + assert.Error(t, err) } else { - assert.Nil(t, err) + assert.NoError(t, err) } }) } @@ -54,17 +57,23 @@ func TestBuildProxyMode(t *testing.T) { io.WriteString(w, "Proxied") })) defer proxyServer.Close() - makeServer := func(mode killgrave.ProxyMode) (*Server, func()) { + + makeServer := func(mode killgrave.ProxyMode) (*Server, func() error) { router := mux.NewRouter() httpServer := &http.Server{Handler: router} + proxyServer, err := NewProxy(proxyServer.URL, mode) - assert.Nil(t, err) - imposterFs := NewImposterFS(afero.NewOsFs()) - server := NewServer("test/testdata/imposters", router, httpServer, proxyServer, false, imposterFs) - return &server, func() { - httpServer.Close() + require.NoError(t, err) + + imposterFs, err := NewImposterFS("test/testdata/imposters") + require.NoError(t, err) + + server := NewServer(router, httpServer, proxyServer, false, imposterFs) + return &server, func() error { + return httpServer.Close() } } + testCases := map[string]struct { mode killgrave.ProxyMode url string @@ -113,7 +122,7 @@ func TestBuildProxyMode(t *testing.T) { s.router.ServeHTTP(w, req) response := w.Result() - body, _ := ioutil.ReadAll(response.Body) + body, _ := io.ReadAll(response.Body) assert.Equal(t, tc.body, string(body)) assert.Equal(t, tc.status, response.StatusCode) @@ -133,14 +142,19 @@ func TestBuildSecureMode(t *testing.T) { httpServer := &http.Server{Handler: router, Addr: ":4430", TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }} + proxyServer, err := NewProxy(proxyServer.URL, mode) - assert.Nil(t, err) - imposterFs := NewImposterFS(afero.NewOsFs()) - server := NewServer("test/testdata/imposters_secure", router, httpServer, proxyServer, true, imposterFs) + require.NoError(t, err) + + imposterFs, err := NewImposterFS("test/testdata/imposters_secure") + require.NoError(t, err) + + server := NewServer(router, httpServer, proxyServer, true, imposterFs) return &server, func() { httpServer.Close() } } + testCases := map[string]struct { mode killgrave.ProxyMode url string diff --git a/internal/server/http/test/testdata/malformatted_imposters/create_gopher.imp.json b/internal/server/http/test/testdata/malformed_imposters/create_gopher.imp.json similarity index 100% rename from internal/server/http/test/testdata/malformatted_imposters/create_gopher.imp.json rename to internal/server/http/test/testdata/malformed_imposters/create_gopher.imp.json