-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from bancodobrasil/develop
promote changes to master branch
- Loading branch information
Showing
20 changed files
with
1,001 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
*.dll | ||
*.so | ||
*.dylib | ||
*.env | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,42 +2,97 @@ package adapter | |
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/bancodobrasil/featws-resolver-adapter-go/config" | ||
// Specificate the docs package | ||
_ "github.com/bancodobrasil/featws-resolver-adapter-go/docs" | ||
"github.com/bancodobrasil/featws-resolver-adapter-go/routes" | ||
"github.com/bancodobrasil/featws-resolver-adapter-go/services" | ||
ginMonitor "github.com/bancodobrasil/gin-monitor" | ||
"github.com/gin-gonic/gin" | ||
"github.com/prometheus/client_golang/prometheus/promhttp" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/viper" | ||
ginlogrus "github.com/toorop/gin-logrus" | ||
) | ||
|
||
func setupLog() { | ||
log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) | ||
func init() { | ||
ex, err := os.Executable() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
exePath := filepath.Dir(ex) | ||
viper.AddConfigPath(exePath) | ||
viper.SetConfigType("env") | ||
viper.SetConfigName(".env") | ||
|
||
log.SetOutput(os.Stdout) | ||
replacer := strings.NewReplacer(".", "_") | ||
viper.SetEnvKeyReplacer(replacer) | ||
viper.AutomaticEnv() | ||
viper.SetDefault("EXTERNAL_HOST", "localhost:7000") | ||
viper.SetDefault("RESOLVER_LOG_JSON", false) | ||
viper.SetDefault("RESOLVER_LOG_LEVEL", "error") | ||
viper.SetDefault("RESOLVER_SERVICE_NAME", "resolver-adapter-go") | ||
if err := viper.ReadInConfig(); err == nil { | ||
log.Infof("Using config file: %s", viper.ConfigFileUsed()) | ||
} | ||
} | ||
|
||
log.SetLevel(log.DebugLevel) | ||
// Config ... | ||
type Config struct { | ||
Port string | ||
} | ||
|
||
// Config contains all settings of module | ||
var Config = config.Config{} | ||
// @title FeatWS Resolver Adapter | ||
|
||
// @version 1.0 | ||
|
||
// @description Resolver Adapter Project is a library to provide resolvers to other projects | ||
|
||
// @termsOfService http://swagger.io/terms/ | ||
|
||
// @contact.name API Support | ||
|
||
// @contact.url http://www.swagger.io/support | ||
|
||
// Run start the resolver server with resolverFunc | ||
func Run(resolverFunc services.ResolverFunc) { | ||
// @contact.email [email protected] | ||
|
||
setupLog() | ||
// @license.name Apache 2.0 | ||
|
||
err := config.LoadConfig(&Config) | ||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html | ||
|
||
// @host localhost:7000 | ||
|
||
// @BasePath /api/v1 | ||
|
||
// @x-extension-openapi {"example": "value on a json format"} | ||
|
||
// Run ... | ||
func Run(resolverFunc services.ResolverFunc, config Config) error { | ||
|
||
InitLogger() | ||
|
||
monitor, err := ginMonitor.New("v0.0.1-rc8", ginMonitor.DefaultErrorMessageKey, ginMonitor.DefaultBuckets) | ||
if err != nil { | ||
log.Fatalf("Não foi possível carregar as configurações: %s\n", err) | ||
panic(err) | ||
} | ||
|
||
gin.DefaultWriter = log.StandardLogger().WriterLevel(log.DebugLevel) | ||
gin.DefaultErrorWriter = log.StandardLogger().WriterLevel(log.ErrorLevel) | ||
|
||
services.SetupResolver(resolverFunc) | ||
|
||
router := gin.New() | ||
// Register ginLogrus log format to gin | ||
router.Use(ginlogrus.Logger(log.StandardLogger()), gin.Recovery()) | ||
|
||
// Register gin-monitor middleware | ||
router.Use(monitor.Prometheus()) | ||
// Register metrics endpoint | ||
router.GET("/metrics", gin.WrapH(promhttp.Handler())) | ||
routes.SetupRoutes(router) | ||
routes.APIRoutes(router) | ||
|
||
port := Config.Port | ||
|
||
router.Run(":" + port) | ||
return router.Run(":" + config.Port) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package adapter | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"crypto/tls" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
"os" | ||
"sort" | ||
"testing" | ||
"time" | ||
|
||
"github.com/bancodobrasil/featws-resolver-adapter-go/types" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
const ( | ||
labelContextTest string = "adapter_context_test" | ||
labelLoadTest string = "adapter_load_test" | ||
labelLoadSystemError string = "adapter_load_system_error" | ||
msgErrorContextMissing string = "Context missing" | ||
msgErrorLoadSystemError string = "This resolver doesn't work for this loads %v" | ||
msgEchoContext string = "#Echo# %s" | ||
messageText string = "Lorem ipsum dolor sit amet" | ||
urlResolver string = "http://localhost:7000/api/v1/resolve/" | ||
contentType string = "application/text" | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
setup() | ||
code := m.Run() | ||
shutdown() | ||
os.Exit(code) | ||
} | ||
|
||
func setup() { | ||
go func() { | ||
Run(resolverTest, Config{ | ||
Port: "7000", | ||
}) | ||
}() | ||
// have to wait for the goroutine to start and run the server | ||
// otherwise the main thread will complete | ||
time.Sleep(5 * time.Millisecond) | ||
} | ||
|
||
func shutdown() {} | ||
|
||
func resolverTest(ctx context.Context, resolveInput types.ResolveInput, resolveOutput *types.ResolveOutput) { | ||
sort.Strings(resolveInput.Load) | ||
if contains(resolveInput.Load, labelLoadTest) { | ||
contextValue, ok := resolveInput.Context[labelContextTest] | ||
if !ok { | ||
resolveOutput.Errors[labelLoadTest] = msgErrorContextMissing | ||
} else { | ||
resolveOutput.Context[labelLoadTest] = fmt.Sprintf(msgEchoContext, contextValue) | ||
} | ||
|
||
} else { | ||
resolveOutput.Errors[labelLoadSystemError] = fmt.Sprintf(msgErrorLoadSystemError, resolveInput.Load) | ||
} | ||
} | ||
|
||
func contains(s []string, searchterm string) bool { | ||
i := sort.SearchStrings(s, searchterm) | ||
return i < len(s) && s[i] == searchterm | ||
} | ||
|
||
func TestAdapterSuccess(t *testing.T) { | ||
resolveOutput := testRequest(t, labelContextTest, messageText, labelLoadTest) | ||
assert.Equal(t, resolveOutput.Context[labelLoadTest], fmt.Sprintf(msgEchoContext, messageText)) | ||
} | ||
|
||
func TestAdapterLabelInvalid(t *testing.T) { | ||
resolveOutput := testRequest(t, labelContextTest, messageText, "label_invalid") | ||
assert.Equal(t, resolveOutput.Errors[labelLoadSystemError], fmt.Sprintf(msgErrorLoadSystemError, []string{"label_invalid"})) | ||
} | ||
|
||
func TestAdapterContextInvalid(t *testing.T) { | ||
resolveOutput := testRequest(t, "context_invalid", messageText, labelLoadTest) | ||
assert.Equal(t, resolveOutput.Errors[labelLoadTest], msgErrorContextMissing) | ||
} | ||
|
||
func testRequest(t *testing.T, context string, data string, load string) *types.ResolveOutput { | ||
tr := &http.Transport{ | ||
TLSClientConfig: &tls.Config{ | ||
InsecureSkipVerify: true, | ||
}, | ||
} | ||
|
||
client := &http.Client{Transport: tr} | ||
|
||
body, _ := json.Marshal(types.ResolveInput{ | ||
Context: map[string]interface{}{ | ||
context: data, | ||
}, | ||
Load: []string{load}, | ||
}) | ||
|
||
postBody := bytes.NewBuffer((body)) | ||
|
||
defer client.CloseIdleConnections() | ||
|
||
resp, err := client.Post(urlResolver, contentType, postBody) | ||
|
||
assert.NoError(t, err) | ||
assert.Equal(t, "200 OK", resp.Status) | ||
|
||
defer resp.Body.Close() | ||
|
||
resBody, err := ioutil.ReadAll(resp.Body) | ||
assert.NoError(t, err) | ||
|
||
resolveOutput := types.ResolveOutput{ | ||
Context: make(map[string]interface{}), | ||
Errors: make(map[string]interface{}), | ||
} | ||
json.Unmarshal(resBody, &resolveOutput) | ||
|
||
return &resolveOutput | ||
|
||
} | ||
|
||
// go test -bench . -run="none" -v -count=5 | ||
|
||
func BenchmarkAdapterResolver(b *testing.B) { | ||
b.ResetTimer() | ||
b.RunParallel(func(pb *testing.PB) { | ||
for pb.Next() { | ||
testRequestBench(labelContextTest, messageText, labelLoadTest) | ||
} | ||
}) | ||
} | ||
|
||
func testRequestBench(context string, data string, load string) { | ||
tr := &http.Transport{ | ||
TLSClientConfig: &tls.Config{ | ||
InsecureSkipVerify: true, | ||
}, | ||
} | ||
|
||
client := &http.Client{Transport: tr} | ||
|
||
body, _ := json.Marshal(types.ResolveInput{ | ||
Context: map[string]interface{}{ | ||
context: data, | ||
}, | ||
Load: []string{load}, | ||
}) | ||
|
||
postBody := bytes.NewBuffer((body)) | ||
|
||
defer client.CloseIdleConnections() | ||
|
||
resp, err := client.Post(urlResolver, contentType, postBody) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
if resp.StatusCode != 200 { | ||
log.Fatal("Http response status not equals 200") | ||
} | ||
|
||
defer resp.Body.Close() | ||
|
||
resBody, err := ioutil.ReadAll(resp.Body) | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
resolveOutput := types.ResolveOutput{ | ||
Context: make(map[string]interface{}), | ||
Errors: make(map[string]interface{}), | ||
} | ||
|
||
err = json.Unmarshal(resBody, &resolveOutput) | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package controllers | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
// HealthLiveHandler ... | ||
func HealthLiveHandler() gin.HandlerFunc { | ||
return func(c *gin.Context) { | ||
c.String(http.StatusOK, "Application is live!!!") | ||
} | ||
|
||
} |
Oops, something went wrong.