Moved endpoint handling to new module
- introduce new endpoints module - introduce Endpoint and EndpointManager - introduce new Logging abstraction API to allow proper mocking - add error return value to Start and Shutdown of endpoints - add mocks of some internals to allow easier testing - add generate target to take care of all code generation
This commit is contained in:
parent
f4ca8e91f2
commit
9236a38be0
38 changed files with 1586 additions and 119 deletions
|
@ -3,7 +3,7 @@
|
||||||
before:
|
before:
|
||||||
hooks:
|
hooks:
|
||||||
# You may remove this if you don't use go modules.
|
# You may remove this if you don't use go modules.
|
||||||
- make plugins
|
- make handlers
|
||||||
builds:
|
builds:
|
||||||
- id: "default"
|
- id: "default"
|
||||||
ldflags:
|
ldflags:
|
||||||
|
|
14
Makefile
14
Makefile
|
@ -3,6 +3,7 @@ DIR = $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
BUILD_PATH = $(DIR)/main.go
|
BUILD_PATH = $(DIR)/main.go
|
||||||
PKGS = $(shell go list ./...)
|
PKGS = $(shell go list ./...)
|
||||||
TEST_PKGS = $(shell find . -type f -name "*_test.go" -not -path "./plugins/*" -printf '%h\n' | sort -u)
|
TEST_PKGS = $(shell find . -type f -name "*_test.go" -not -path "./plugins/*" -printf '%h\n' | sort -u)
|
||||||
|
GO_GEN_FILES = $(shell grep -rnwl --include="*.go" "go:generate" $(DIR))
|
||||||
GOARGS = GOOS=linux GOARCH=amd64
|
GOARGS = GOOS=linux GOARCH=amd64
|
||||||
GO_BUILD_ARGS = -ldflags="-w -s"
|
GO_BUILD_ARGS = -ldflags="-w -s"
|
||||||
GO_CONTAINER_BUILD_ARGS = -ldflags="-w -s" -a -installsuffix cgo
|
GO_CONTAINER_BUILD_ARGS = -ldflags="-w -s" -a -installsuffix cgo
|
||||||
|
@ -11,10 +12,8 @@ BINARY_NAME = inetmock
|
||||||
PLUGINS = $(wildcard $(DIR)plugins/*/.)
|
PLUGINS = $(wildcard $(DIR)plugins/*/.)
|
||||||
DEBUG_PORT = 2345
|
DEBUG_PORT = 2345
|
||||||
DEBUG_ARGS?= --development-logs=true
|
DEBUG_ARGS?= --development-logs=true
|
||||||
INETMOCK_PLUGINS_DIRECTORY = $(DIR)
|
|
||||||
|
|
||||||
.PHONY: clean all format deps update-deps compile debug snapshot-release test cli-cover-report html-cover-report plugins $(PLUGINS)
|
|
||||||
|
|
||||||
|
.PHONY: clean all format deps update-deps compile debug generate snapshot-release test cli-cover-report html-cover-report plugins $(PLUGINS) $(.PHONY: clean all format deps update-deps compile debug generate snapshot-release test cli-cover-report html-cover-report plugins $(PLUGINS) $(GO_GEN_FILES)
|
||||||
all: clean format compile test plugins
|
all: clean format compile test plugins
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -44,8 +43,8 @@ else
|
||||||
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(DIR)$(BINARY_NAME) $(BUILD_PATH)
|
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(DIR)$(BINARY_NAME) $(BUILD_PATH)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
debug: export INETMOCK_PLUGINS_DIRECTORY = $(DIR)
|
||||||
debug:
|
debug:
|
||||||
@export INETMOCK_PLUGINS_DIRECTORY
|
|
||||||
dlv exec $(DIR)$(BINARY_NAME) \
|
dlv exec $(DIR)$(BINARY_NAME) \
|
||||||
--headless \
|
--headless \
|
||||||
--listen=:2345 \
|
--listen=:2345 \
|
||||||
|
@ -53,6 +52,11 @@ debug:
|
||||||
--accept-multiclient \
|
--accept-multiclient \
|
||||||
-- $(DEBUG_ARGS)
|
-- $(DEBUG_ARGS)
|
||||||
|
|
||||||
|
generate:
|
||||||
|
@for go_gen_target in $(GO_GEN_FILES); do \
|
||||||
|
go generate $$go_gen_target; \
|
||||||
|
done
|
||||||
|
|
||||||
snapshot-release:
|
snapshot-release:
|
||||||
@goreleaser release --snapshot --skip-publish --rm-dist
|
@goreleaser release --snapshot --skip-publish --rm-dist
|
||||||
|
|
||||||
|
@ -63,7 +67,7 @@ test:
|
||||||
cli-cover-report:
|
cli-cover-report:
|
||||||
@go tool cover -func=cov.out
|
@go tool cover -func=cov.out
|
||||||
|
|
||||||
html-cover-report:
|
html-cover-report: test
|
||||||
@go tool cover -html=cov.out -o .coverage.html
|
@go tool cover -html=cov.out -o .coverage.html
|
||||||
|
|
||||||
plugins: $(PLUGINS)
|
plugins: $(PLUGINS)
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
|
github.com/golang/mock v1.4.3
|
||||||
github.com/mitchellh/mapstructure v1.2.2 // indirect
|
github.com/mitchellh/mapstructure v1.2.2 // indirect
|
||||||
github.com/pelletier/go-toml v1.7.0 // indirect
|
github.com/pelletier/go-toml v1.7.0 // indirect
|
||||||
github.com/spf13/afero v1.2.2 // indirect
|
github.com/spf13/afero v1.2.2 // indirect
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -33,7 +33,10 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
@ -177,6 +180,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -186,6 +190,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
@ -215,3 +220,5 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/baez90/inetmock/internal/endpoints"
|
||||||
"github.com/baez90/inetmock/internal/plugins"
|
"github.com/baez90/inetmock/internal/plugins"
|
||||||
"github.com/baez90/inetmock/pkg/logging"
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/baez90/inetmock/pkg/path"
|
"github.com/baez90/inetmock/pkg/path"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,6 +27,7 @@ func initApp() (err error) {
|
||||||
)
|
)
|
||||||
logger, _ = logging.CreateLogger()
|
logger, _ = logging.CreateLogger()
|
||||||
registry := plugins.Registry()
|
registry := plugins.Registry()
|
||||||
|
endpointManager = endpoints.NewEndpointManager(logger)
|
||||||
|
|
||||||
if err = rootCmd.ParseFlags(os.Args); err != nil {
|
if err = rootCmd.ParseFlags(os.Args); err != nil {
|
||||||
return
|
return
|
||||||
|
@ -40,12 +43,18 @@ func initApp() (err error) {
|
||||||
|
|
||||||
viperInst := viper.GetViper()
|
viperInst := viper.GetViper()
|
||||||
pluginDir := viperInst.GetString("plugins-directory")
|
pluginDir := viperInst.GetString("plugins-directory")
|
||||||
|
pluginLoadStartTime := time.Now()
|
||||||
if err = registry.LoadPlugins(pluginDir); err != nil {
|
if err = registry.LoadPlugins(pluginDir); err != nil {
|
||||||
logger.Error("Failed to load plugins",
|
logger.Error("Failed to load plugins",
|
||||||
zap.String("pluginsDirectory", pluginDir),
|
zap.String("pluginsDirectory", pluginDir),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
pluginLoadDuration := time.Since(pluginLoadStartTime)
|
||||||
|
logger.Info(
|
||||||
|
"loading plugins completed",
|
||||||
|
zap.Duration("pluginLoadDuration", pluginLoadDuration),
|
||||||
|
)
|
||||||
|
|
||||||
pluginsCmd.AddCommand(registry.PluginCommands()...)
|
pluginsCmd.AddCommand(registry.PluginCommands()...)
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,20 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
"github.com/baez90/inetmock/internal/plugins"
|
"github.com/baez90/inetmock/internal/endpoints"
|
||||||
"github.com/baez90/inetmock/pkg/api"
|
"github.com/baez90/inetmock/pkg/api"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
rootCmd = cobra.Command{
|
rootCmd = cobra.Command{
|
||||||
Use: "",
|
Use: "",
|
||||||
Short: "INetMock is lightweight internet mock",
|
Short: "INetMock is lightweight internet mock",
|
||||||
|
@ -27,6 +27,7 @@ var (
|
||||||
developmentLogs bool
|
developmentLogs bool
|
||||||
handlers []api.ProtocolHandler
|
handlers []api.ProtocolHandler
|
||||||
appConfig = config.CreateConfig()
|
appConfig = config.CreateConfig()
|
||||||
|
endpointManager endpoints.EndpointManager
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -39,28 +40,21 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func startInetMock(cmd *cobra.Command, args []string) {
|
func startInetMock(cmd *cobra.Command, args []string) {
|
||||||
registry := plugins.Registry()
|
for endpointName := range viper.GetStringMap(config.EndpointsKey) {
|
||||||
var wg sync.WaitGroup
|
handlerSubConfig := viper.Sub(strings.Join([]string{config.EndpointsKey, endpointName}, "."))
|
||||||
|
handlerConfig := config.CreateMultiHandlerConfig(handlerSubConfig)
|
||||||
//todo introduce endpoint type and move startup and shutdown to this type
|
if err := endpointManager.CreateEndpoint(endpointName, handlerConfig); err != nil {
|
||||||
|
|
||||||
for key, val := range viper.GetStringMap(config.EndpointsKey) {
|
|
||||||
handlerSubConfig := viper.Sub(strings.Join([]string{config.EndpointsKey, key, config.OptionsKey}, "."))
|
|
||||||
pluginConfig := config.CreateHandlerConfig(val, handlerSubConfig)
|
|
||||||
logger.Info(key, zap.Any("value", pluginConfig))
|
|
||||||
|
|
||||||
if handler, ok := registry.HandlerForName(pluginConfig.HandlerName()); ok {
|
|
||||||
handlers = append(handlers, handler)
|
|
||||||
go startEndpoint(handler, pluginConfig, logger)
|
|
||||||
wg.Add(1)
|
|
||||||
} else {
|
|
||||||
logger.Warn(
|
logger.Warn(
|
||||||
"no matching handler registered",
|
"error occurred while creating endpoint",
|
||||||
zap.String("handler", pluginConfig.HandlerName()),
|
zap.String("endpointName", endpointName),
|
||||||
|
zap.String("handlerName", handlerConfig.HandlerName()),
|
||||||
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endpointManager.StartEndpoints()
|
||||||
|
|
||||||
signalChannel := make(chan os.Signal, 1)
|
signalChannel := make(chan os.Signal, 1)
|
||||||
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
|
|
||||||
|
@ -72,35 +66,7 @@ func startInetMock(cmd *cobra.Command, args []string) {
|
||||||
zap.String("signal", s.String()),
|
zap.String("signal", s.String()),
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, handler := range handlers {
|
endpointManager.ShutdownEndpoints()
|
||||||
go shutdownEndpoint(handler, &wg, logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func startEndpoint(handler api.ProtocolHandler, config config.HandlerConfig, logger *zap.Logger) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
logger.Fatal(
|
|
||||||
"recovered panic during startup of endpoint",
|
|
||||||
zap.Any("recovered", r),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
handler.Start(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func shutdownEndpoint(handler api.ProtocolHandler, wg *sync.WaitGroup, logger *zap.Logger) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
logger.Fatal(
|
|
||||||
"recovered panic during shutdown of endpoint",
|
|
||||||
zap.Any("recovered", r),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
handler.Shutdown(wg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecuteRootCommand() error {
|
func ExecuteRootCommand() error {
|
||||||
|
|
|
@ -4,19 +4,36 @@ import "github.com/spf13/viper"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pluginConfigKey = "handler"
|
pluginConfigKey = "handler"
|
||||||
listenAddressConfigKey = "listenaddress"
|
listenAddressConfigKey = "listenAddress"
|
||||||
portConfigKey = "port"
|
portConfigKey = "port"
|
||||||
|
portsConfigKey = "ports"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type HandlerConfig interface {
|
||||||
|
HandlerName() string
|
||||||
|
ListenAddress() string
|
||||||
|
Port() uint16
|
||||||
|
Options() *viper.Viper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandlerConfig(handlerName string, port uint16, listenAddress string, options *viper.Viper) HandlerConfig {
|
||||||
|
return &handlerConfig{
|
||||||
|
handlerName: handlerName,
|
||||||
|
port: port,
|
||||||
|
listenAddress: listenAddress,
|
||||||
|
options: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type handlerConfig struct {
|
type handlerConfig struct {
|
||||||
pluginName string
|
handlerName string
|
||||||
port uint16
|
port uint16
|
||||||
listenAddress string
|
listenAddress string
|
||||||
options *viper.Viper
|
options *viper.Viper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h handlerConfig) HandlerName() string {
|
func (h handlerConfig) HandlerName() string {
|
||||||
return h.pluginName
|
return h.handlerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h handlerConfig) ListenAddress() string {
|
func (h handlerConfig) ListenAddress() string {
|
||||||
|
@ -30,20 +47,3 @@ func (h handlerConfig) Port() uint16 {
|
||||||
func (h handlerConfig) Options() *viper.Viper {
|
func (h handlerConfig) Options() *viper.Viper {
|
||||||
return h.options
|
return h.options
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlerConfig interface {
|
|
||||||
HandlerName() string
|
|
||||||
ListenAddress() string
|
|
||||||
Port() uint16
|
|
||||||
Options() *viper.Viper
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateHandlerConfig(configMap interface{}, subConfig *viper.Viper) HandlerConfig {
|
|
||||||
underlyingMap := configMap.(map[string]interface{})
|
|
||||||
return &handlerConfig{
|
|
||||||
pluginName: underlyingMap[pluginConfigKey].(string),
|
|
||||||
listenAddress: underlyingMap[listenAddressConfigKey].(string),
|
|
||||||
port: uint16(underlyingMap[portConfigKey].(int)),
|
|
||||||
options: subConfig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
167
internal/config/handler_config_test.go
Normal file
167
internal/config/handler_config_test.go
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_handlerConfig_HandlerName(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
port uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty HandlerName for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected HandlerName for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
},
|
||||||
|
want: "sampleHandler",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := handlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
port: tt.fields.port,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := h.HandlerName(); got != tt.want {
|
||||||
|
t.Errorf("HandlerName() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handlerConfig_ListenAddress(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
port uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty ListenAddress for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected ListenAddress for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
},
|
||||||
|
want: "0.0.0.0",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := handlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
port: tt.fields.port,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := h.ListenAddress(); got != tt.want {
|
||||||
|
t.Errorf("ListenAddress() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handlerConfig_Options(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
port uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want *viper.Viper
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get nil Options for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected Options for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
options: viper.New(),
|
||||||
|
},
|
||||||
|
want: viper.New(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := handlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
port: tt.fields.port,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := h.Options(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Options() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handlerConfig_Port(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
port uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want uint16
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty Port for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected Port for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
port: 80,
|
||||||
|
},
|
||||||
|
want: 80,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := handlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
port: tt.fields.port,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := h.Port(); got != tt.want {
|
||||||
|
t.Errorf("Port() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ type Config interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c config) InitConfig(flags *pflag.FlagSet) {
|
func (c config) InitConfig(flags *pflag.FlagSet) {
|
||||||
|
|
48
internal/config/multi_handler_config.go
Normal file
48
internal/config/multi_handler_config.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MultiHandlerConfig interface {
|
||||||
|
HandlerName() string
|
||||||
|
ListenAddress() string
|
||||||
|
Ports() []uint16
|
||||||
|
Options() *viper.Viper
|
||||||
|
HandlerConfigs() []HandlerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type multiHandlerConfig struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMultiHandlerConfig(handlerName string, ports []uint16, listenAddress string, options *viper.Viper) MultiHandlerConfig {
|
||||||
|
return &multiHandlerConfig{handlerName: handlerName, ports: ports, listenAddress: listenAddress, options: options}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m multiHandlerConfig) HandlerName() string {
|
||||||
|
return m.handlerName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m multiHandlerConfig) ListenAddress() string {
|
||||||
|
return m.listenAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m multiHandlerConfig) Ports() []uint16 {
|
||||||
|
return m.ports
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m multiHandlerConfig) Options() *viper.Viper {
|
||||||
|
return m.options
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m multiHandlerConfig) HandlerConfigs() []HandlerConfig {
|
||||||
|
configs := make([]HandlerConfig, 0)
|
||||||
|
for _, port := range m.ports {
|
||||||
|
configs = append(configs, NewHandlerConfig(m.handlerName, port, m.listenAddress, m.options))
|
||||||
|
}
|
||||||
|
return configs
|
||||||
|
}
|
240
internal/config/multi_handler_config_test.go
Normal file
240
internal/config/multi_handler_config_test.go
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_multiHandlerConfig_HandlerConfigs(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []HandlerConfig
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty array if no ports are set",
|
||||||
|
fields: fields{},
|
||||||
|
want: make([]HandlerConfig, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get a single handler config if only one port is set",
|
||||||
|
fields: fields{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
ports: []uint16{80},
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: nil,
|
||||||
|
},
|
||||||
|
want: []HandlerConfig{
|
||||||
|
&handlerConfig{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
port: 80,
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get multiple handler configs if only one port is set",
|
||||||
|
fields: fields{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
ports: []uint16{80, 8080},
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: nil,
|
||||||
|
},
|
||||||
|
want: []HandlerConfig{
|
||||||
|
&handlerConfig{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
port: 80,
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: nil,
|
||||||
|
},
|
||||||
|
&handlerConfig{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
port: 8080,
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := multiHandlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
ports: tt.fields.ports,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := m.HandlerConfigs(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("HandlerConfigs() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_multiHandlerConfig_HandlerName(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty handler name for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected handler name for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
},
|
||||||
|
want: "sampleHandler",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := multiHandlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
ports: tt.fields.ports,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := m.HandlerName(); got != tt.want {
|
||||||
|
t.Errorf("HandlerName() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_multiHandlerConfig_ListenAddress(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty ListenAddress for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected ListenAddress for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
},
|
||||||
|
want: "0.0.0.0",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := multiHandlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
ports: tt.fields.ports,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := m.ListenAddress(); got != tt.want {
|
||||||
|
t.Errorf("ListenAddress() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_multiHandlerConfig_Options(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want *viper.Viper
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get nil Options for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected Options for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
options: viper.New(),
|
||||||
|
},
|
||||||
|
want: viper.New(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := multiHandlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
ports: tt.fields.ports,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := m.Options(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Options() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_multiHandlerConfig_Ports(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlerName string
|
||||||
|
ports []uint16
|
||||||
|
listenAddress string
|
||||||
|
options *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []uint16
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get empty Ports for uninitialized struct",
|
||||||
|
fields: fields{},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get expected Ports for initialized struct",
|
||||||
|
fields: fields{
|
||||||
|
ports: []uint16{80, 8080},
|
||||||
|
},
|
||||||
|
want: []uint16{80, 8080},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := multiHandlerConfig{
|
||||||
|
handlerName: tt.fields.handlerName,
|
||||||
|
ports: tt.fields.ports,
|
||||||
|
listenAddress: tt.fields.listenAddress,
|
||||||
|
options: tt.fields.options,
|
||||||
|
}
|
||||||
|
if got := m.Ports(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Ports() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
26
internal/config/parsing.go
Normal file
26
internal/config/parsing.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import "github.com/spf13/viper"
|
||||||
|
|
||||||
|
func CreateMultiHandlerConfig(handlerConfig *viper.Viper) MultiHandlerConfig {
|
||||||
|
return NewMultiHandlerConfig(
|
||||||
|
handlerConfig.GetString(pluginConfigKey),
|
||||||
|
portsFromConfig(handlerConfig),
|
||||||
|
handlerConfig.GetString(listenAddressConfigKey),
|
||||||
|
handlerConfig.Sub(OptionsKey),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func portsFromConfig(handlerConfig *viper.Viper) (ports []uint16) {
|
||||||
|
if portsInt := handlerConfig.GetIntSlice(portsConfigKey); len(portsInt) > 0 {
|
||||||
|
for _, port := range portsInt {
|
||||||
|
ports = append(ports, uint16(port))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if portInt := handlerConfig.GetInt(portConfigKey); portInt > 0 {
|
||||||
|
ports = append(ports, uint16(portInt))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
145
internal/config/parsing_test.go
Normal file
145
internal/config/parsing_test.go
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateMultiHandlerConfig(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
handlerConfig *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want MultiHandlerConfig
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get simple multiHandlerConfig from config",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
handler: sampleHandler
|
||||||
|
listenAddress: 0.0.0.0
|
||||||
|
ports:
|
||||||
|
- 80
|
||||||
|
- 8080
|
||||||
|
options: {}
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
want: &multiHandlerConfig{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
ports: []uint16{80, 8080},
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: viper.New(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get more complex multiHandlerConfig from config",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
handler: sampleHandler
|
||||||
|
listenAddress: 0.0.0.0
|
||||||
|
ports:
|
||||||
|
- 80
|
||||||
|
- 8080
|
||||||
|
options:
|
||||||
|
optionA: asdf
|
||||||
|
optionB: as1234
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
want: &multiHandlerConfig{
|
||||||
|
handlerName: "sampleHandler",
|
||||||
|
ports: []uint16{80, 8080},
|
||||||
|
listenAddress: "0.0.0.0",
|
||||||
|
options: configFromString(`
|
||||||
|
nesting:
|
||||||
|
optionA: asdf
|
||||||
|
optionB: as1234
|
||||||
|
`).Sub("nesting"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := CreateMultiHandlerConfig(tt.args.handlerConfig); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("CreateMultiHandlerConfig() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_portsFromConfig(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
handlerConfig *viper.Viper
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantPorts []uint16
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Empty array if config value is not set",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: viper.New(),
|
||||||
|
},
|
||||||
|
wantPorts: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Array of one if `port` is set",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
port: 80
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
wantPorts: []uint16{80},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Array of one if `ports` is set as array",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
ports:
|
||||||
|
- 80
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
wantPorts: []uint16{80},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Array of two if `ports` is set as array",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
ports:
|
||||||
|
- 80
|
||||||
|
- 8080
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
wantPorts: []uint16{80, 8080},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Array of two if `port` is set as array",
|
||||||
|
args: args{
|
||||||
|
handlerConfig: configFromString(`
|
||||||
|
ports:
|
||||||
|
- 80
|
||||||
|
- 8080
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
wantPorts: []uint16{80, 8080},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotPorts := portsFromConfig(tt.args.handlerConfig); !reflect.DeepEqual(gotPorts, tt.wantPorts) {
|
||||||
|
t.Errorf("portsFromConfig() = %v, want %v", gotPorts, tt.wantPorts)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func configFromString(yaml string) (config *viper.Viper) {
|
||||||
|
config = viper.New()
|
||||||
|
config.SetConfigType("yaml")
|
||||||
|
_ = config.ReadConfig(bytes.NewBufferString(yaml))
|
||||||
|
return
|
||||||
|
}
|
31
internal/endpoints/endpoint.go
Normal file
31
internal/endpoints/endpoint.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//go:generate mockgen -source=endpoint.go -destination=./../../mock/endpoint_mock.go -package=mock
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Endpoint interface {
|
||||||
|
Start() error
|
||||||
|
Shutdown() error
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type endpoint struct {
|
||||||
|
name string
|
||||||
|
handler api.ProtocolHandler
|
||||||
|
config config.HandlerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e endpoint) Name() string {
|
||||||
|
return e.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpoint) Start() (err error) {
|
||||||
|
return e.handler.Start(e.config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpoint) Shutdown() (err error) {
|
||||||
|
return e.handler.Shutdown()
|
||||||
|
}
|
130
internal/endpoints/endpoint_manager.go
Normal file
130
internal/endpoints/endpoint_manager.go
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/internal/plugins"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EndpointManager interface {
|
||||||
|
RegisteredEndpoints() []Endpoint
|
||||||
|
StartedEndpoints() []Endpoint
|
||||||
|
CreateEndpoint(name string, multiHandlerConfig config.MultiHandlerConfig) error
|
||||||
|
StartEndpoints()
|
||||||
|
ShutdownEndpoints()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEndpointManager(logger logging.Logger) EndpointManager {
|
||||||
|
return &endpointManager{
|
||||||
|
logger: logger,
|
||||||
|
registry: plugins.Registry(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type endpointManager struct {
|
||||||
|
logger logging.Logger
|
||||||
|
registeredEndpoints []Endpoint
|
||||||
|
properlyStartedEndpoints []Endpoint
|
||||||
|
registry plugins.HandlerRegistry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e endpointManager) RegisteredEndpoints() []Endpoint {
|
||||||
|
return e.registeredEndpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e endpointManager) StartedEndpoints() []Endpoint {
|
||||||
|
return e.properlyStartedEndpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpointManager) CreateEndpoint(name string, multiHandlerConfig config.MultiHandlerConfig) (err error) {
|
||||||
|
if handler, ok := e.registry.HandlerForName(multiHandlerConfig.HandlerName()); ok {
|
||||||
|
for _, handlerConfig := range multiHandlerConfig.HandlerConfigs() {
|
||||||
|
e.registeredEndpoints = append(e.registeredEndpoints, &endpoint{
|
||||||
|
name: name,
|
||||||
|
handler: handler,
|
||||||
|
config: handlerConfig,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("no matching handler registered for name %s", multiHandlerConfig.HandlerName())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpointManager) StartEndpoints() {
|
||||||
|
startTime := time.Now()
|
||||||
|
for _, endpoint := range e.registeredEndpoints {
|
||||||
|
endpointLogger := e.logger.With(
|
||||||
|
zap.String("endpoint", endpoint.Name()),
|
||||||
|
)
|
||||||
|
endpointLogger.Info("Starting endpoint")
|
||||||
|
if ok := startEndpoint(endpoint, endpointLogger); ok {
|
||||||
|
e.properlyStartedEndpoints = append(e.properlyStartedEndpoints, endpoint)
|
||||||
|
endpointLogger.Info("successfully started endpoint")
|
||||||
|
} else {
|
||||||
|
endpointLogger.Error("error occurred during endpoint startup - will be skipped for now")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpointStartupDuration := time.Since(startTime)
|
||||||
|
e.logger.Info(
|
||||||
|
"Startup of all endpoints completed",
|
||||||
|
zap.Duration("startupTime", endpointStartupDuration),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpointManager) ShutdownEndpoints() {
|
||||||
|
var waitGroup sync.WaitGroup
|
||||||
|
waitGroup.Add(len(e.properlyStartedEndpoints))
|
||||||
|
|
||||||
|
for _, endpoint := range e.properlyStartedEndpoints {
|
||||||
|
endpointLogger := e.logger.With(
|
||||||
|
zap.String("endpoint", endpoint.Name()),
|
||||||
|
)
|
||||||
|
endpointLogger.Info("Triggering shutdown of endpoint")
|
||||||
|
go shutdownEndpoint(endpoint, endpointLogger, &waitGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
waitGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func startEndpoint(ep Endpoint, logger logging.Logger) (success bool) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
logger.Fatal(
|
||||||
|
"recovered panic during startup of endpoint",
|
||||||
|
zap.Any("recovered", r),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err := ep.Start(); err != nil {
|
||||||
|
logger.Error(
|
||||||
|
"failed to start endpoint",
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
success = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func shutdownEndpoint(ep Endpoint, logger logging.Logger, wg *sync.WaitGroup) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
logger.Fatal(
|
||||||
|
"recovered panic during shutdown of endpoint",
|
||||||
|
zap.Any("recovered", r),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
if err := ep.Shutdown(); err != nil {
|
||||||
|
logger.Error(
|
||||||
|
"Failed to shutdown endpoint",
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
116
internal/endpoints/endpoint_manager_test.go
Normal file
116
internal/endpoints/endpoint_manager_test.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/internal/plugins"
|
||||||
|
"github.com/baez90/inetmock/mock"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_endpointManager_CreateEndpoint(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
logger logging.Logger
|
||||||
|
registeredEndpoints []Endpoint
|
||||||
|
properlyStartedEndpoints []Endpoint
|
||||||
|
registry plugins.HandlerRegistry
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
name string
|
||||||
|
multiHandlerConfig config.MultiHandlerConfig
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
wantEndpoints int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Test add endpoint",
|
||||||
|
wantErr: false,
|
||||||
|
wantEndpoints: 1,
|
||||||
|
fields: fields{
|
||||||
|
logger: func() logging.Logger {
|
||||||
|
return mock.NewMockLogger(gomock.NewController(t))
|
||||||
|
}(),
|
||||||
|
registeredEndpoints: nil,
|
||||||
|
properlyStartedEndpoints: nil,
|
||||||
|
registry: func() plugins.HandlerRegistry {
|
||||||
|
registry := mock.NewMockHandlerRegistry(gomock.NewController(t))
|
||||||
|
registry.
|
||||||
|
EXPECT().
|
||||||
|
HandlerForName("sampleHandler").
|
||||||
|
MinTimes(1).
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(mock.NewMockProtocolHandler(gomock.NewController(t)), true)
|
||||||
|
return registry
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
name: "sampleEndpoint",
|
||||||
|
multiHandlerConfig: config.NewMultiHandlerConfig(
|
||||||
|
"sampleHandler",
|
||||||
|
[]uint16{80},
|
||||||
|
"0.0.0.0",
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test add unknown handler",
|
||||||
|
wantErr: true,
|
||||||
|
wantEndpoints: 0,
|
||||||
|
fields: fields{
|
||||||
|
logger: func() logging.Logger {
|
||||||
|
return mock.NewMockLogger(gomock.NewController(t))
|
||||||
|
}(),
|
||||||
|
registeredEndpoints: nil,
|
||||||
|
properlyStartedEndpoints: nil,
|
||||||
|
registry: func() plugins.HandlerRegistry {
|
||||||
|
registry := mock.NewMockHandlerRegistry(gomock.NewController(t))
|
||||||
|
registry.
|
||||||
|
EXPECT().
|
||||||
|
HandlerForName("sampleHandler").
|
||||||
|
MinTimes(1).
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(nil, false)
|
||||||
|
return registry
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
name: "sampleEndpoint",
|
||||||
|
multiHandlerConfig: config.NewMultiHandlerConfig(
|
||||||
|
"sampleHandler",
|
||||||
|
[]uint16{80},
|
||||||
|
"0.0.0.0",
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := &endpointManager{
|
||||||
|
logger: tt.fields.logger,
|
||||||
|
registeredEndpoints: tt.fields.registeredEndpoints,
|
||||||
|
properlyStartedEndpoints: tt.fields.properlyStartedEndpoints,
|
||||||
|
registry: tt.fields.registry,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := e.CreateEndpoint(tt.args.name, tt.args.multiHandlerConfig); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("CreateEndpoint() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(e.RegisteredEndpoints()) != tt.wantEndpoints {
|
||||||
|
t.Errorf("RegisteredEndpoints() = %d, want = 1", len(e.RegisteredEndpoints()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(e.RegisteredEndpoints()) > 0 && e.RegisteredEndpoints()[0].Name() != tt.args.name {
|
||||||
|
t.Errorf("Name() = %s, want = %s", e.RegisteredEndpoints()[0].Name(), tt.args.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
179
internal/endpoints/endpoint_test.go
Normal file
179
internal/endpoints/endpoint_test.go
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/mock"
|
||||||
|
"github.com/baez90/inetmock/pkg/api"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_endpoint_Name(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
name string
|
||||||
|
handler api.ProtocolHandler
|
||||||
|
config config.HandlerConfig
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Empty Name if struct is uninitialized",
|
||||||
|
fields: fields{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Expected Name if struct is initialized",
|
||||||
|
fields: fields{
|
||||||
|
name: "sampleHandler",
|
||||||
|
},
|
||||||
|
want: "sampleHandler",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := endpoint{
|
||||||
|
name: tt.fields.name,
|
||||||
|
handler: tt.fields.handler,
|
||||||
|
config: tt.fields.config,
|
||||||
|
}
|
||||||
|
if got := e.Name(); got != tt.want {
|
||||||
|
t.Errorf("Name() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_endpoint_Shutdown(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
name string
|
||||||
|
handler api.ProtocolHandler
|
||||||
|
config config.HandlerConfig
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Expect no error if mocked handler does not return one",
|
||||||
|
fields: fields{
|
||||||
|
handler: func() api.ProtocolHandler {
|
||||||
|
handler := mock.NewMockProtocolHandler(gomock.NewController(t))
|
||||||
|
handler.EXPECT().
|
||||||
|
Shutdown().
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(nil)
|
||||||
|
return handler
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Expect error if mocked handler returns one",
|
||||||
|
fields: fields{
|
||||||
|
handler: func() api.ProtocolHandler {
|
||||||
|
handler := mock.NewMockProtocolHandler(gomock.NewController(t))
|
||||||
|
handler.EXPECT().
|
||||||
|
Shutdown().
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(fmt.Errorf(""))
|
||||||
|
return handler
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := &endpoint{
|
||||||
|
name: tt.fields.name,
|
||||||
|
handler: tt.fields.handler,
|
||||||
|
config: tt.fields.config,
|
||||||
|
}
|
||||||
|
if err := e.Shutdown(); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Shutdown() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_endpoint_Start(t *testing.T) {
|
||||||
|
|
||||||
|
demoHandlerConfig := config.NewHandlerConfig(
|
||||||
|
"sampleHandler",
|
||||||
|
80,
|
||||||
|
"0.0.0.0",
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
name string
|
||||||
|
handler api.ProtocolHandler
|
||||||
|
config config.HandlerConfig
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Expect no error if mocked handler does not return one",
|
||||||
|
fields: fields{
|
||||||
|
handler: func() api.ProtocolHandler {
|
||||||
|
handler := mock.NewMockProtocolHandler(gomock.NewController(t))
|
||||||
|
handler.EXPECT().
|
||||||
|
Start(nil).
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(nil)
|
||||||
|
return handler
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Expect error if mocked handler returns one",
|
||||||
|
fields: fields{
|
||||||
|
handler: func() api.ProtocolHandler {
|
||||||
|
handler := mock.NewMockProtocolHandler(gomock.NewController(t))
|
||||||
|
handler.EXPECT().
|
||||||
|
Start(nil).
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(fmt.Errorf(""))
|
||||||
|
return handler
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Expect config to be passed to Start call",
|
||||||
|
fields: fields{
|
||||||
|
config: demoHandlerConfig,
|
||||||
|
handler: func() api.ProtocolHandler {
|
||||||
|
handler := mock.NewMockProtocolHandler(gomock.NewController(t))
|
||||||
|
handler.EXPECT().
|
||||||
|
Start(demoHandlerConfig).
|
||||||
|
MaxTimes(1).
|
||||||
|
Return(fmt.Errorf(""))
|
||||||
|
return handler
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := &endpoint{
|
||||||
|
name: tt.fields.name,
|
||||||
|
handler: tt.fields.handler,
|
||||||
|
config: tt.fields.config,
|
||||||
|
}
|
||||||
|
if err := e.Start(); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Start() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:generate mockgen -source=loading.go -destination=./../../mock/plugins_mock.go -package=mock
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -42,7 +43,7 @@ func (h *handlerRegistry) HandlerForName(handlerName string) (instance api.Proto
|
||||||
|
|
||||||
func (h *handlerRegistry) RegisterHandler(handlerName string, handlerProvider api.PluginInstanceFactory, subCommands ...*cobra.Command) {
|
func (h *handlerRegistry) RegisterHandler(handlerName string, handlerProvider api.PluginInstanceFactory, subCommands ...*cobra.Command) {
|
||||||
if _, exists := h.handlers[handlerName]; exists {
|
if _, exists := h.handlers[handlerName]; exists {
|
||||||
panic(fmt.Sprintf("plugin %s already registered - there's something strange...in the neighborhood"))
|
panic(fmt.Sprintf("handler with name %s is already registered - there's something strange...in the neighborhood", handlerName))
|
||||||
}
|
}
|
||||||
h.handlers[handlerName] = handlerProvider
|
h.handlers[handlerName] = handlerProvider
|
||||||
|
|
||||||
|
|
109
internal/plugins/loading_test.go
Normal file
109
internal/plugins/loading_test.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/baez90/inetmock/pkg/api"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_handlerRegistry_PluginCommands(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlers map[string]api.PluginInstanceFactory
|
||||||
|
pluginCommands []*cobra.Command
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []*cobra.Command
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Default is an nil array of commands",
|
||||||
|
fields: fields{},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Returns a copy of the given array of commands",
|
||||||
|
fields: fields{
|
||||||
|
pluginCommands: []*cobra.Command{
|
||||||
|
{
|
||||||
|
Use: "my-super-command",
|
||||||
|
Short: "bla bla bla, description",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []*cobra.Command{
|
||||||
|
{
|
||||||
|
Use: "my-super-command",
|
||||||
|
Short: "bla bla bla, description",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := handlerRegistry{
|
||||||
|
handlers: tt.fields.handlers,
|
||||||
|
pluginCommands: tt.fields.pluginCommands,
|
||||||
|
}
|
||||||
|
if got := h.PluginCommands(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("PluginCommands() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handlerRegistry_HandlerForName(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
handlers map[string]api.PluginInstanceFactory
|
||||||
|
pluginCommands []*cobra.Command
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
handlerName string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantInstance api.ProtocolHandler
|
||||||
|
wantOk bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "No instance if nothing is registered",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{},
|
||||||
|
wantInstance: nil,
|
||||||
|
wantOk: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Nil instance from pseudo factory",
|
||||||
|
fields: fields{
|
||||||
|
handlers: map[string]api.PluginInstanceFactory{
|
||||||
|
"pseudo": func() api.ProtocolHandler {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
handlerName: "pseudo",
|
||||||
|
},
|
||||||
|
wantInstance: nil,
|
||||||
|
wantOk: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := &handlerRegistry{
|
||||||
|
handlers: tt.fields.handlers,
|
||||||
|
pluginCommands: tt.fields.pluginCommands,
|
||||||
|
}
|
||||||
|
gotInstance, gotOk := h.HandlerForName(tt.args.handlerName)
|
||||||
|
if !reflect.DeepEqual(gotInstance, tt.wantInstance) {
|
||||||
|
t.Errorf("HandlerForName() gotInstance = %v, want %v", gotInstance, tt.wantInstance)
|
||||||
|
}
|
||||||
|
if gotOk != tt.wantOk {
|
||||||
|
t.Errorf("HandlerForName() gotOk = %v, want %v", gotOk, tt.wantOk)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,9 @@ endpoints:
|
||||||
plainHttp:
|
plainHttp:
|
||||||
handler: http_mock
|
handler: http_mock
|
||||||
listenAddress: 0.0.0.0
|
listenAddress: 0.0.0.0
|
||||||
port: 80
|
ports:
|
||||||
|
- 80
|
||||||
|
- 8080
|
||||||
options:
|
options:
|
||||||
<<: *httpResponseRules
|
<<: *httpResponseRules
|
||||||
proxy:
|
proxy:
|
||||||
|
@ -46,7 +48,9 @@ endpoints:
|
||||||
httpsDowngrade:
|
httpsDowngrade:
|
||||||
handler: tls_interceptor
|
handler: tls_interceptor
|
||||||
listenAddress: 0.0.0.0
|
listenAddress: 0.0.0.0
|
||||||
port: 443
|
ports:
|
||||||
|
- 443
|
||||||
|
- 8443
|
||||||
options:
|
options:
|
||||||
<<: *tlsOptions
|
<<: *tlsOptions
|
||||||
target:
|
target:
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
//go:generate mockgen -source=protocol_handler.go -destination=./../../mock/protocol_handler_mock.go -package=mock
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PluginInstanceFactory func() ProtocolHandler
|
type PluginInstanceFactory func() ProtocolHandler
|
||||||
|
@ -11,6 +11,6 @@ type PluginInstanceFactory func() ProtocolHandler
|
||||||
type LoggingFactory func() (*zap.Logger, error)
|
type LoggingFactory func() (*zap.Logger, error)
|
||||||
|
|
||||||
type ProtocolHandler interface {
|
type ProtocolHandler interface {
|
||||||
Start(config config.HandlerConfig)
|
Start(config config.HandlerConfig) error
|
||||||
Shutdown(wg *sync.WaitGroup)
|
Shutdown() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,10 @@ func ConfigureLogging(
|
||||||
) {
|
) {
|
||||||
loggingConfig.Level = level
|
loggingConfig.Level = level
|
||||||
loggingConfig.Development = developmentLogging
|
loggingConfig.Development = developmentLogging
|
||||||
|
if initialFields != nil {
|
||||||
loggingConfig.InitialFields = initialFields
|
loggingConfig.InitialFields = initialFields
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ParseLevel(levelString string) zap.AtomicLevel {
|
func ParseLevel(levelString string) zap.AtomicLevel {
|
||||||
switch strings.ToLower(levelString) {
|
switch strings.ToLower(levelString) {
|
||||||
|
@ -37,6 +39,10 @@ func ParseLevel(levelString string) zap.AtomicLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateLogger() (*zap.Logger, error) {
|
func CreateLogger() (Logger, error) {
|
||||||
return loggingConfig.Build()
|
if zapLogger, err := loggingConfig.Build(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return NewLogger(zapLogger), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
166
pkg/logging/factory_test.go
Normal file
166
pkg/logging/factory_test.go
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseLevel(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
levelString string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want zap.AtomicLevel
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Test parse DEBUG level",
|
||||||
|
args: args{
|
||||||
|
levelString: "DEBUG",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.DebugLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse DeBuG level",
|
||||||
|
args: args{
|
||||||
|
levelString: "DeBuG",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.DebugLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse INFO level",
|
||||||
|
args: args{
|
||||||
|
levelString: "INFO",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse InFo level",
|
||||||
|
args: args{
|
||||||
|
levelString: "InFo",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse WARN level",
|
||||||
|
args: args{
|
||||||
|
levelString: "WARN",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.WarnLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse WaRn level",
|
||||||
|
args: args{
|
||||||
|
levelString: "WaRn",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.WarnLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse ERROR level",
|
||||||
|
args: args{
|
||||||
|
levelString: "ERROR",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.ErrorLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse ErRoR level",
|
||||||
|
args: args{
|
||||||
|
levelString: "ErRoR",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.ErrorLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse FATAL level",
|
||||||
|
args: args{
|
||||||
|
levelString: "FATAL",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.FatalLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test parse FaTaL level",
|
||||||
|
args: args{
|
||||||
|
levelString: "FaTaL",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.FatalLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fallback to INFO level if unknown level",
|
||||||
|
args: args{
|
||||||
|
levelString: "asdf23423",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fallback to INFO level if no level",
|
||||||
|
args: args{
|
||||||
|
levelString: "",
|
||||||
|
},
|
||||||
|
want: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := ParseLevel(tt.args.levelString); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("ParseLevel() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigureLogging(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
level zap.AtomicLevel
|
||||||
|
developmentLogging bool
|
||||||
|
initialFields map[string]interface{}
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Test configure defaults",
|
||||||
|
args: args{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test configure with initialFields",
|
||||||
|
args: args{
|
||||||
|
initialFields: map[string]interface{}{
|
||||||
|
"asdf": "hello, World",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test configure development logging enabled",
|
||||||
|
args: args{
|
||||||
|
developmentLogging: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test configure log level",
|
||||||
|
args: args{
|
||||||
|
level: zap.NewAtomicLevelAt(zap.FatalLevel),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ConfigureLogging(tt.args.level, tt.args.developmentLogging, tt.args.initialFields)
|
||||||
|
if loggingConfig.Development != tt.args.developmentLogging {
|
||||||
|
t.Errorf("loggingConfig.Development = %t, want %t", loggingConfig.Development, tt.args.developmentLogging)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if loggingConfig.Level != tt.args.level {
|
||||||
|
t.Errorf("loggingConfig.Level = %v, want %v", loggingConfig.Level, tt.args.level)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.args.initialFields != nil && !reflect.DeepEqual(loggingConfig.InitialFields, tt.args.initialFields) {
|
||||||
|
t.Errorf("loggingConfig.InitialFields = %v, want %v", loggingConfig.InitialFields, tt.args.initialFields)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
60
pkg/logging/logger.go
Normal file
60
pkg/logging/logger.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
//go:generate mockgen -source=logger.go -destination=./../../mock/logger_mock.go -package=mock
|
||||||
|
package logging
|
||||||
|
|
||||||
|
import "go.uber.org/zap"
|
||||||
|
|
||||||
|
type Logger interface {
|
||||||
|
Named(s string) Logger
|
||||||
|
With(fields ...zap.Field) Logger
|
||||||
|
Debug(msg string, fields ...zap.Field)
|
||||||
|
Info(msg string, fields ...zap.Field)
|
||||||
|
Warn(msg string, fields ...zap.Field)
|
||||||
|
Error(msg string, fields ...zap.Field)
|
||||||
|
Panic(msg string, fields ...zap.Field)
|
||||||
|
Fatal(msg string, fields ...zap.Field)
|
||||||
|
Sync() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type logger struct {
|
||||||
|
underlyingLogger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger(underlyingLogger *zap.Logger) *logger {
|
||||||
|
return &logger{underlyingLogger: underlyingLogger}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Named(s string) Logger {
|
||||||
|
return NewLogger(l.underlyingLogger.Named(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) With(fields ...zap.Field) Logger {
|
||||||
|
return NewLogger(l.underlyingLogger.With(fields...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Debug(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Debug(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Info(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Info(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Warn(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Warn(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Error(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Error(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Panic(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Panic(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Fatal(msg string, fields ...zap.Field) {
|
||||||
|
l.underlyingLogger.Fatal(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logger) Sync() error {
|
||||||
|
return l.underlyingLogger.Sync()
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
@ -187,6 +188,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -196,6 +198,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
@ -225,3 +228,5 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -3,17 +3,17 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type dnsHandler struct {
|
type dnsHandler struct {
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
dnsServer []*dns.Server
|
dnsServer []*dns.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dnsHandler) Start(config config.HandlerConfig) {
|
func (d *dnsHandler) Start(config config.HandlerConfig) (err error) {
|
||||||
options := loadFromConfig(config.Options())
|
options := loadFromConfig(config.Options())
|
||||||
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ func (d *dnsHandler) Start(config config.HandlerConfig) {
|
||||||
for _, dnsServer := range d.dnsServer {
|
for _, dnsServer := range d.dnsServer {
|
||||||
go d.startServer(dnsServer)
|
go d.startServer(dnsServer)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dnsHandler) startServer(dnsServer *dns.Server) {
|
func (d *dnsHandler) startServer(dnsServer *dns.Server) {
|
||||||
|
@ -62,7 +63,7 @@ func (d *dnsHandler) startServer(dnsServer *dns.Server) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dnsHandler) Shutdown(wg *sync.WaitGroup) {
|
func (d *dnsHandler) Shutdown() error {
|
||||||
d.logger.Info("shutting down DNS mock")
|
d.logger.Info("shutting down DNS mock")
|
||||||
for _, dnsServer := range d.dnsServer {
|
for _, dnsServer := range d.dnsServer {
|
||||||
if err := dnsServer.Shutdown(); err != nil {
|
if err := dnsServer.Shutdown(); err != nil {
|
||||||
|
@ -72,5 +73,5 @@ func (d *dnsHandler) Shutdown(wg *sync.WaitGroup) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Done()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -8,7 +9,7 @@ import (
|
||||||
type regexHandler struct {
|
type regexHandler struct {
|
||||||
routes []resolverRule
|
routes []resolverRule
|
||||||
fallback ResolverFallback
|
fallback ResolverFallback
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r2 *regexHandler) AddRule(rule resolverRule) {
|
func (r2 *regexHandler) AddRule(rule resolverRule) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
@ -177,6 +178,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -186,6 +188,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
@ -215,3 +218,5 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +17,7 @@ func (p *httpHandler) setupRoute(rule targetRule) {
|
||||||
p.router.Handler(rule.Pattern(), createHandlerForTarget(p.logger, rule.response))
|
p.router.Handler(rule.Pattern(), createHandlerForTarget(p.logger, rule.response))
|
||||||
}
|
}
|
||||||
|
|
||||||
func createHandlerForTarget(logger *zap.Logger, targetPath string) http.Handler {
|
func createHandlerForTarget(logger logging.Logger, targetPath string) http.Handler {
|
||||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||||
headerWriter := &bytes.Buffer{}
|
headerWriter := &bytes.Buffer{}
|
||||||
request.Header.Write(headerWriter)
|
request.Header.Write(headerWriter)
|
||||||
|
|
|
@ -3,9 +3,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -13,12 +13,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpHandler struct {
|
type httpHandler struct {
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
router *RegexpHandler
|
router *RegexpHandler
|
||||||
server *http.Server
|
server *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *httpHandler) Start(config config.HandlerConfig) {
|
func (p *httpHandler) Start(config config.HandlerConfig) (err error) {
|
||||||
options := loadFromConfig(config.Options())
|
options := loadFromConfig(config.Options())
|
||||||
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
||||||
p.server = &http.Server{Addr: addr, Handler: p.router}
|
p.server = &http.Server{Addr: addr, Handler: p.router}
|
||||||
|
@ -31,18 +31,22 @@ func (p *httpHandler) Start(config config.HandlerConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
go p.startServer()
|
go p.startServer()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *httpHandler) Shutdown(wg *sync.WaitGroup) {
|
func (p *httpHandler) Shutdown() (err error) {
|
||||||
p.logger.Info("Shutting down HTTP mock")
|
p.logger.Info("Shutting down HTTP mock")
|
||||||
if err := p.server.Close(); err != nil {
|
if err = p.server.Close(); err != nil {
|
||||||
p.logger.Error(
|
p.logger.Error(
|
||||||
"failed to shutdown HTTP server",
|
"failed to shutdown HTTP server",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"failed to shutdown HTTP server: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
wg.Done()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *httpHandler) startServer() {
|
func (p *httpHandler) startServer() {
|
||||||
|
|
|
@ -38,6 +38,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
@ -182,6 +183,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -191,6 +193,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
@ -222,3 +225,5 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -3,10 +3,10 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gopkg.in/elazarl/goproxy.v1"
|
"gopkg.in/elazarl/goproxy.v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -14,12 +14,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpProxy struct {
|
type httpProxy struct {
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
proxy *goproxy.ProxyHttpServer
|
proxy *goproxy.ProxyHttpServer
|
||||||
server *http.Server
|
server *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpProxy) Start(config config.HandlerConfig) {
|
func (h *httpProxy) Start(config config.HandlerConfig) (err error) {
|
||||||
options := loadFromConfig(config.Options())
|
options := loadFromConfig(config.Options())
|
||||||
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
||||||
h.server = &http.Server{Addr: addr, Handler: h.proxy}
|
h.server = &http.Server{Addr: addr, Handler: h.proxy}
|
||||||
|
@ -33,6 +33,7 @@ func (h *httpProxy) Start(config config.HandlerConfig) {
|
||||||
}
|
}
|
||||||
h.proxy.OnRequest().Do(proxyHandler)
|
h.proxy.OnRequest().Do(proxyHandler)
|
||||||
go h.startProxy()
|
go h.startProxy()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpProxy) startProxy() {
|
func (h *httpProxy) startProxy() {
|
||||||
|
@ -44,13 +45,18 @@ func (h *httpProxy) startProxy() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpProxy) Shutdown(wg *sync.WaitGroup) {
|
func (h *httpProxy) Shutdown() (err error) {
|
||||||
defer wg.Done()
|
|
||||||
h.logger.Info("Shutting down HTTP proxy")
|
h.logger.Info("Shutting down HTTP proxy")
|
||||||
if err := h.server.Close(); err != nil {
|
if err = h.server.Close(); err != nil {
|
||||||
h.logger.Error(
|
h.logger.Error(
|
||||||
"failed to shutdown proxy endpoint",
|
"failed to shutdown proxy endpoint",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"failed to shutdown proxy endpoint: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gopkg.in/elazarl/goproxy.v1"
|
"gopkg.in/elazarl/goproxy.v1"
|
||||||
"io"
|
"io"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
|
|
||||||
type proxyHttpHandler struct {
|
type proxyHttpHandler struct {
|
||||||
options httpProxyOptions
|
options httpProxyOptions
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/baez90/inetmock/pkg/path"
|
"github.com/baez90/inetmock/pkg/path"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -22,7 +23,7 @@ type certStore struct {
|
||||||
caPrivateKey interface{}
|
caPrivateKey interface{}
|
||||||
certCache map[string]*tls.Certificate
|
certCache map[string]*tls.Certificate
|
||||||
timeSourceInstance timeSource
|
timeSourceInstance timeSource
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *certStore) timeSource() timeSource {
|
func (cs *certStore) timeSource() timeSource {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -85,7 +86,8 @@ func Test_generateDomainCert(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
logger, _ := zap.NewDevelopment()
|
zapLogger, _ := zap.NewDevelopment()
|
||||||
|
logger := logging.NewLogger(zapLogger)
|
||||||
|
|
||||||
certStore := certStore{
|
certStore := certStore{
|
||||||
options: options,
|
options: options,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"time"
|
"time"
|
||||||
|
@ -14,7 +15,7 @@ const (
|
||||||
generateCANotAfterRelative = "not-after"
|
generateCANotAfterRelative = "not-after"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateCACmd(logger *zap.Logger) *cobra.Command {
|
func generateCACmd(logger logging.Logger) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "generate-ca",
|
Use: "generate-ca",
|
||||||
Short: "Generate a new CA certificate and corresponding key",
|
Short: "Generate a new CA certificate and corresponding key",
|
||||||
|
@ -31,7 +32,7 @@ func generateCACmd(logger *zap.Logger) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDurationFlag(cmd *cobra.Command, flagName string, logger *zap.Logger) (val time.Duration, err error) {
|
func getDurationFlag(cmd *cobra.Command, flagName string, logger logging.Logger) (val time.Duration, err error) {
|
||||||
if val, err = cmd.Flags().GetDuration(flagName); err != nil {
|
if val, err = cmd.Flags().GetDuration(flagName); err != nil {
|
||||||
logger.Error(
|
logger.Error(
|
||||||
"failed to parse parse flag",
|
"failed to parse parse flag",
|
||||||
|
@ -42,7 +43,7 @@ func getDurationFlag(cmd *cobra.Command, flagName string, logger *zap.Logger) (v
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStringFlag(cmd *cobra.Command, flagName string, logger *zap.Logger) (val string, err error) {
|
func getStringFlag(cmd *cobra.Command, flagName string, logger logging.Logger) (val string, err error) {
|
||||||
if val, err = cmd.Flags().GetString(flagName); err != nil {
|
if val, err = cmd.Flags().GetString(flagName); err != nil {
|
||||||
logger.Error(
|
logger.Error(
|
||||||
"failed to parse parse flag",
|
"failed to parse parse flag",
|
||||||
|
@ -53,7 +54,7 @@ func getStringFlag(cmd *cobra.Command, flagName string, logger *zap.Logger) (val
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGenerateCA(logger *zap.Logger) func(cmd *cobra.Command, args []string) {
|
func runGenerateCA(logger logging.Logger) func(cmd *cobra.Command, args []string) {
|
||||||
return func(cmd *cobra.Command, args []string) {
|
return func(cmd *cobra.Command, args []string) {
|
||||||
var certOutPath, keyOutPath, curveName string
|
var certOutPath, keyOutPath, curveName string
|
||||||
var notBefore, notAfter time.Duration
|
var notBefore, notAfter time.Duration
|
||||||
|
|
|
@ -34,6 +34,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
@ -177,6 +178,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU=
|
||||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -186,6 +188,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
@ -215,3 +218,5 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/baez90/inetmock/internal/config"
|
"github.com/baez90/inetmock/internal/config"
|
||||||
|
"github.com/baez90/inetmock/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -16,7 +17,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tlsInterceptor struct {
|
type tlsInterceptor struct {
|
||||||
logger *zap.Logger
|
logger logging.Logger
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
certStore *certStore
|
certStore *certStore
|
||||||
options *tlsOptions
|
options *tlsOptions
|
||||||
|
@ -25,8 +26,7 @@ type tlsInterceptor struct {
|
||||||
currentConnections []*proxyConn
|
currentConnections []*proxyConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tlsInterceptor) Start(config config.HandlerConfig) {
|
func (t *tlsInterceptor) Start(config config.HandlerConfig) (err error) {
|
||||||
var err error
|
|
||||||
t.options = loadFromConfig(config.Options())
|
t.options = loadFromConfig(config.Options())
|
||||||
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
addr := fmt.Sprintf("%s:%d", config.ListenAddress(), config.Port())
|
||||||
|
|
||||||
|
@ -46,6 +46,11 @@ func (t *tlsInterceptor) Start(config config.HandlerConfig) {
|
||||||
"failed to initialize CA cert",
|
"failed to initialize CA cert",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"failed to initialize CA cert: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCaPool := x509.NewCertPool()
|
rootCaPool := x509.NewCertPool()
|
||||||
|
@ -61,13 +66,18 @@ func (t *tlsInterceptor) Start(config config.HandlerConfig) {
|
||||||
"failed to create tls listener",
|
"failed to create tls listener",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"failed to create tls listener: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go t.startListener()
|
go t.startListener()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tlsInterceptor) Shutdown(wg *sync.WaitGroup) {
|
func (t *tlsInterceptor) Shutdown() (err error) {
|
||||||
t.logger.Info("Shutting down TLS interceptor")
|
t.logger.Info("Shutting down TLS interceptor")
|
||||||
t.shutdownRequested = true
|
t.shutdownRequested = true
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
@ -78,17 +88,21 @@ func (t *tlsInterceptor) Shutdown(wg *sync.WaitGroup) {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
wg.Done()
|
return
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
for _, proxyConn := range t.currentConnections {
|
for _, proxyConn := range t.currentConnections {
|
||||||
if err := proxyConn.Close(); err != nil {
|
if err = proxyConn.Close(); err != nil {
|
||||||
t.logger.Error(
|
t.logger.Error(
|
||||||
"error while closing remaining proxy connections",
|
"error while closing remaining proxy connections",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"error while closing remaining proxy connections: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Done()
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue