diff --git a/Dockerfile b/Dockerfile index e00435f..e56f64a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.14-alpine as build +FROM golang:1.15-alpine as build # Create appuser and group. ARG USER=inetmock diff --git a/cmd/inetmock/main.go b/cmd/inetmock/main.go index 850c038..7eaa048 100644 --- a/cmd/inetmock/main.go +++ b/cmd/inetmock/main.go @@ -8,6 +8,7 @@ import ( _ "github.com/baez90/inetmock/plugins/dns_mock" _ "github.com/baez90/inetmock/plugins/http_mock" _ "github.com/baez90/inetmock/plugins/http_proxy" + _ "github.com/baez90/inetmock/plugins/metrics_exporter" _ "github.com/baez90/inetmock/plugins/tls_interceptor" ) diff --git a/config.yaml b/config.yaml index 3bd2087..1a3c774 100644 --- a/config.yaml +++ b/config.yaml @@ -85,4 +85,11 @@ endpoints: options: target: ipAddress: 127.0.0.1 - port: 53 \ No newline at end of file + port: 53 + metrics: + handler: metrics_exporter + listenAddress: 0.0.0.0 + ports: + - 9110 + options: + route: /metrics \ No newline at end of file diff --git a/go.mod b/go.mod index 54875dd..b660b8c 100644 --- a/go.mod +++ b/go.mod @@ -1,36 +1,20 @@ module github.com/baez90/inetmock -go 1.14 +go 1.15 require ( - github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1 // indirect - github.com/elazarl/goproxy/ext v0.0.0-20200426045556-49ad98f6dac1 // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/golang/mock v1.4.3 + github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.1 - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/miekg/dns v1.0.14 - github.com/mitchellh/mapstructure v1.3.2 // indirect + github.com/miekg/dns v1.1.31 github.com/olekukonko/tablewriter v0.0.4 - github.com/pelletier/go-toml v1.8.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/spf13/afero v1.2.2 // indirect - github.com/spf13/cast v1.3.1 // indirect + github.com/prometheus/client_golang v1.7.1 github.com/spf13/cobra v1.0.0 - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.7.0 - go.uber.org/zap v1.15.0 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect - golang.org/x/mod v0.3.0 // indirect - golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect - golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 // indirect - golang.org/x/tools v0.0.0-20200624060801-dcbf2a9ed15d // indirect - google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 // indirect + github.com/spf13/viper v1.7.1 + go.uber.org/zap v1.16.0 google.golang.org/grpc v1.29.1 - google.golang.org/protobuf v1.24.0 + google.golang.org/protobuf v1.23.0 gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153 - gopkg.in/ini.v1 v1.57.0 // indirect - gopkg.in/yaml.v2 v2.3.0 + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 ) diff --git a/go.sum b/go.sum index 1f32001..3778b71 100644 --- a/go.sum +++ b/go.sum @@ -16,17 +16,25 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -42,22 +50,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1 h1:TEmChtx8+IeOghiySC8kQIr0JZOdKUmRmmkuRDuYs3E= -github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d h1:rtM8HsT3NG37YPjz8sYSbUSdElP9lUsQENYzJDZDUBE= +github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= -github.com/elazarl/goproxy/ext v0.0.0-20200426045556-49ad98f6dac1 h1:nCR2gi9ueTfwN7mmtDbWEFPF+I+mW3PAJFiqlwfaJHE= -github.com/elazarl/goproxy/ext v0.0.0-20200426045556-49ad98f6dac1/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/elazarl/goproxy/ext v0.0.0-20200809112317-0581fc3aee2d h1:st1tmvy+4duoRj+RaeeJoECWCWM015fBtf/4aR+hhqk= +github.com/elazarl/goproxy/ext v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -70,6 +79,8 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 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/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -79,7 +90,6 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -89,6 +99,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -129,6 +140,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -136,6 +148,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -145,14 +158,20 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= +github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -160,35 +179,54 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= -github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= -github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= @@ -198,20 +236,24 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.4.0 h1:jsLTaI1zwYO3vjrzHalkVcIHXTNmdQFepW4OI8H3+x8= +github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -221,6 +263,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -233,30 +277,38 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977 h1:yH6opeNE+0SY+7pXT4gclZUoKHogXeC2EvOSHGOMGPU= +golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -276,10 +328,7 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -294,10 +343,13 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo= +golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -305,6 +357,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -317,19 +370,27 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -351,10 +412,9 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/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-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200624060801-dcbf2a9ed15d h1:Y4+kqqCbf46GCNf04uMqIlDYf1FuyTqSLDGywuWdRUI= -golang.org/x/tools v0.0.0-20200624060801-dcbf2a9ed15d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -376,17 +436,14 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a h1:Ob5/580gVHBJZgXnff1cZDbG+xLtMVE5mDRTe+nIsX4= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 h1:i+Aiej6cta/Frzp13/swvwz5O00kYcSe0A/C5Wd7zX8= -google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -394,28 +451,33 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153 h1:i2sumy6EgvN2dbX7HPhoDc7hLyoym3OYdU5HlvUUrpE= gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153/go.mod h1:xzjpkyedLMz3EXUTBbkRuuGPsxfsBX3Sy7J6kC9Gvoc= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= -gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10= +gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/endpoints/constants.go b/internal/endpoints/constants.go new file mode 100644 index 0000000..1e9f681 --- /dev/null +++ b/internal/endpoints/constants.go @@ -0,0 +1,7 @@ +package endpoints + +import "time" + +const ( + shutdownTimeout = 5 * time.Second +) diff --git a/internal/endpoints/endpoint.go b/internal/endpoints/endpoint.go index c4e97ce..820c7e3 100644 --- a/internal/endpoints/endpoint.go +++ b/internal/endpoints/endpoint.go @@ -1,7 +1,8 @@ -//go:generate mockgen -source=endpoint.go -destination=./../../internal/mock/endpoints/endpoint.mock.go -package=endpoints_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/endpoints/endpoint.mock.go -package=endpoints_mock package endpoints import ( + "context" "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/config" "github.com/google/uuid" @@ -10,7 +11,7 @@ import ( type Endpoint interface { Id() uuid.UUID Start() error - Shutdown() error + Shutdown(ctx context.Context) error Name() string Handler() string Listen() string @@ -48,6 +49,6 @@ func (e *endpoint) Start() (err error) { return e.handler.Start(e.config) } -func (e *endpoint) Shutdown() (err error) { - return e.handler.Shutdown() +func (e *endpoint) Shutdown(ctx context.Context) (err error) { + return e.handler.Shutdown(ctx) } diff --git a/internal/endpoints/endpoint_manager.go b/internal/endpoints/endpoint_manager.go index c74ed41..c251259 100644 --- a/internal/endpoints/endpoint_manager.go +++ b/internal/endpoints/endpoint_manager.go @@ -1,6 +1,7 @@ package endpoints import ( + "context" "fmt" "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/config" @@ -98,30 +99,36 @@ func (e *endpointManager) ShutdownEndpoints() { var waitGroup sync.WaitGroup waitGroup.Add(len(e.properlyStartedEndpoints)) + parentCtx, _ := context.WithTimeout(context.Background(), shutdownTimeout) + + perHandlerTimeout := e.shutdownTimePerEndpoint() + for _, endpoint := range e.properlyStartedEndpoints { + ctx, _ := context.WithTimeout(parentCtx, perHandlerTimeout) endpointLogger := e.logger.With( zap.String("endpoint", endpoint.Name()), ) endpointLogger.Info("Triggering shutdown of endpoint") - go shutdownEndpoint(endpoint, endpointLogger, &waitGroup) + go shutdownEndpoint(ctx, 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), - ) - } - }() - startSuccessful := make(chan bool) go func() { + defer func() { + if r := recover(); r != nil { + logger.Fatal( + "recovered panic during startup of endpoint", + zap.Any("recovered", r), + ) + startSuccessful <- false + } + }() + if err := ep.Start(); err != nil { logger.Error( "failed to start endpoint", @@ -142,7 +149,7 @@ func startEndpoint(ep Endpoint, logger logging.Logger) (success bool) { return } -func shutdownEndpoint(ep Endpoint, logger logging.Logger, wg *sync.WaitGroup) { +func shutdownEndpoint(ctx context.Context, ep Endpoint, logger logging.Logger, wg *sync.WaitGroup) { defer func() { if r := recover(); r != nil { logger.Fatal( @@ -152,7 +159,7 @@ func shutdownEndpoint(ep Endpoint, logger logging.Logger, wg *sync.WaitGroup) { } wg.Done() }() - if err := ep.Shutdown(); err != nil { + if err := ep.Shutdown(ctx); err != nil { logger.Error( "Failed to shutdown endpoint", zap.Error(err), @@ -160,6 +167,10 @@ func shutdownEndpoint(ep Endpoint, logger logging.Logger, wg *sync.WaitGroup) { } } +func (e *endpointManager) shutdownTimePerEndpoint() time.Duration { + return time.Duration((float64(shutdownTimeout) * 0.9) / float64(len(e.properlyStartedEndpoints))) +} + func endpointComponentName(ep Endpoint) string { return fmt.Sprintf("endpoint_%s", ep.Name()) } diff --git a/internal/endpoints/endpoint_test.go b/internal/endpoints/endpoint_test.go index 3ddf5f0..c989bd7 100644 --- a/internal/endpoints/endpoint_test.go +++ b/internal/endpoints/endpoint_test.go @@ -1,14 +1,20 @@ package endpoints import ( + "context" "fmt" - api_mock "github.com/baez90/inetmock/internal/mock/api" + apimock "github.com/baez90/inetmock/internal/mock/api" "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/config" "github.com/golang/mock/gomock" + "reflect" "testing" ) +var ( + anyContext = context.Background() +) + func Test_endpoint_Name(t *testing.T) { type fields struct { name string @@ -62,9 +68,9 @@ func Test_endpoint_Shutdown(t *testing.T) { name: "Expect no error if mocked handler does not return one", fields: fields{ handler: func() api.ProtocolHandler { - handler := api_mock.NewMockProtocolHandler(gomock.NewController(t)) + handler := apimock.NewMockProtocolHandler(gomock.NewController(t)) handler.EXPECT(). - Shutdown(). + Shutdown(gomock.Any()). MaxTimes(1). Return(nil) return handler @@ -76,9 +82,9 @@ func Test_endpoint_Shutdown(t *testing.T) { name: "Expect error if mocked handler returns one", fields: fields{ handler: func() api.ProtocolHandler { - handler := api_mock.NewMockProtocolHandler(gomock.NewController(t)) + handler := apimock.NewMockProtocolHandler(gomock.NewController(t)) handler.EXPECT(). - Shutdown(). + Shutdown(gomock.AssignableToTypeOf(reflect.TypeOf(context.Background()))). MaxTimes(1). Return(fmt.Errorf("")) return handler @@ -94,7 +100,7 @@ func Test_endpoint_Shutdown(t *testing.T) { handler: tt.fields.handler, config: tt.fields.config, } - if err := e.Shutdown(); (err != nil) != tt.wantErr { + if err := e.Shutdown(context.Background()); (err != nil) != tt.wantErr { t.Errorf("Shutdown() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -123,7 +129,7 @@ func Test_endpoint_Start(t *testing.T) { name: "Expect no error if mocked handler does not return one", fields: fields{ handler: func() api.ProtocolHandler { - handler := api_mock.NewMockProtocolHandler(gomock.NewController(t)) + handler := apimock.NewMockProtocolHandler(gomock.NewController(t)) handler.EXPECT(). Start(gomock.Any()). MaxTimes(1). @@ -137,7 +143,7 @@ func Test_endpoint_Start(t *testing.T) { name: "Expect error if mocked handler returns one", fields: fields{ handler: func() api.ProtocolHandler { - handler := api_mock.NewMockProtocolHandler(gomock.NewController(t)) + handler := apimock.NewMockProtocolHandler(gomock.NewController(t)) handler.EXPECT(). Start(gomock.Any()). MaxTimes(1). @@ -152,7 +158,7 @@ func Test_endpoint_Start(t *testing.T) { fields: fields{ config: demoHandlerConfig, handler: func() api.ProtocolHandler { - handler := api_mock.NewMockProtocolHandler(gomock.NewController(t)) + handler := apimock.NewMockProtocolHandler(gomock.NewController(t)) handler.EXPECT(). Start(demoHandlerConfig). MaxTimes(1). diff --git a/internal/format/console_writer.go b/internal/format/console_writer.go index 0a87d12..ce123fb 100644 --- a/internal/format/console_writer.go +++ b/internal/format/console_writer.go @@ -3,7 +3,7 @@ package format import ( "encoding/json" "github.com/olekukonko/tablewriter" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" "io" "strings" ) diff --git a/internal/format/yaml_writer.go b/internal/format/yaml_writer.go index a41d460..0814fda 100644 --- a/internal/format/yaml_writer.go +++ b/internal/format/yaml_writer.go @@ -1,7 +1,7 @@ package format import ( - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) type yamlWriter struct { diff --git a/pkg/api/protocol_handler.go b/pkg/api/protocol_handler.go index d6fb8d3..6146216 100644 --- a/pkg/api/protocol_handler.go +++ b/pkg/api/protocol_handler.go @@ -1,7 +1,8 @@ -//go:generate mockgen -source=protocol_handler.go -destination=./../../internal/mock/api/protocol_handler.mock.go -package=api_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/api/protocol_handler.mock.go -package=api_mock package api import ( + "context" "github.com/baez90/inetmock/pkg/config" "go.uber.org/zap" ) @@ -12,5 +13,5 @@ type LoggingFactory func() (*zap.Logger, error) type ProtocolHandler interface { Start(config config.HandlerConfig) error - Shutdown() error + Shutdown(ctx context.Context) error } diff --git a/pkg/api/registration.go b/pkg/api/registration.go index 043afee..cc05f51 100644 --- a/pkg/api/registration.go +++ b/pkg/api/registration.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=registration.go -destination=./../../internal/mock/plugins/handler_registry.mock.go -package=plugins_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/plugins/handler_registry.mock.go -package=plugins_mock package api import ( diff --git a/pkg/cert/cache.go b/pkg/cert/cache.go index 80afa73..2bf130d 100644 --- a/pkg/cert/cache.go +++ b/pkg/cert/cache.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=cache.go -destination=./../../internal/mock/cert/cert_cache.mock.go -package=cert_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/cert/cert_cache.mock.go -package=cert_mock package cert diff --git a/pkg/cert/time_source.go b/pkg/cert/time_source.go index 1e8abf1..3b98162 100644 --- a/pkg/cert/time_source.go +++ b/pkg/cert/time_source.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=time_source.go -destination=./../../internal/mock/cert/time_source.mock.go -package=cert_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/cert/time_source.mock.go -package=cert_mock package cert diff --git a/pkg/config/handler_config.go b/pkg/config/handler_config.go index 5f523dd..03d28c9 100644 --- a/pkg/config/handler_config.go +++ b/pkg/config/handler_config.go @@ -1,6 +1,9 @@ package config -import "github.com/spf13/viper" +import ( + "fmt" + "github.com/spf13/viper" +) type HandlerConfig struct { HandlerName string @@ -8,3 +11,7 @@ type HandlerConfig struct { ListenAddress string Options *viper.Viper } + +func (h HandlerConfig) ListenAddr() string { + return fmt.Sprintf("%s:%d", h.ListenAddress, h.Port) +} diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go index c38b964..c6e045a 100644 --- a/pkg/logging/logger.go +++ b/pkg/logging/logger.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=logger.go -destination=./../../internal/mock/logging/logger.mock.go -package=logging_mock +//go:generate mockgen -source=$GOFILE -destination=./../../internal/mock/logging/logger.mock.go -package=logging_mock package logging import "go.uber.org/zap" diff --git a/pkg/metrics/metrics_factory.go b/pkg/metrics/metrics_factory.go new file mode 100644 index 0000000..28cc117 --- /dev/null +++ b/pkg/metrics/metrics_factory.go @@ -0,0 +1,47 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +const ( + metricNamespace = "inetmock" +) + +func Gauge(subsystem, name, help string, labelNames ...string) (*prometheus.GaugeVec, error) { + vec := prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: metricNamespace, + Subsystem: subsystem, + Name: name, + Help: help, + }, labelNames) + return vec, prometheus.Register(vec) +} + +func Histogram(subsystem, name, help string, buckets []float64, labelNames ...string) (*prometheus.HistogramVec, error) { + vec := prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: metricNamespace, + Subsystem: subsystem, + Name: name, + Help: help, + Buckets: buckets, + }, + labelNames, + ) + return vec, prometheus.Register(vec) +} + +func Counter(subsystem, name, help string, labelNames ...string) (*prometheus.CounterVec, error) { + vec := prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: metricNamespace, + Subsystem: subsystem, + Name: name, + Help: help, + }, + labelNames, + ) + return vec, prometheus.Register(vec) +} diff --git a/plugins/dns_mock/handler.go b/plugins/dns_mock/handler.go index 7299b8b..489cb70 100644 --- a/plugins/dns_mock/handler.go +++ b/plugins/dns_mock/handler.go @@ -1,7 +1,7 @@ package dns_mock import ( - "fmt" + "context" "github.com/baez90/inetmock/pkg/config" "github.com/baez90/inetmock/pkg/logging" "github.com/miekg/dns" @@ -14,12 +14,21 @@ type dnsHandler struct { } func (d *dnsHandler) Start(config config.HandlerConfig) (err error) { - options := loadFromConfig(config.Options) - addr := fmt.Sprintf("%s:%d", config.ListenAddress, config.Port) + var options dnsOptions + if options, err = loadFromConfig(config.Options); err != nil { + return + } + + listenAddr := config.ListenAddr() + d.logger = d.logger.With( + zap.String("handler_name", config.HandlerName), + zap.String("address", listenAddr), + ) handler := ®exHandler{ - fallback: options.Fallback, - logger: d.logger, + handlerName: config.HandlerName, + fallback: options.Fallback, + logger: d.logger, } for _, rule := range options.Rules { @@ -32,17 +41,17 @@ func (d *dnsHandler) Start(config config.HandlerConfig) (err error) { } d.logger = d.logger.With( - zap.String("address", addr), + zap.String("address", listenAddr), ) d.dnsServer = []*dns.Server{ { - Addr: addr, + Addr: listenAddr, Net: "udp", Handler: handler, }, { - Addr: addr, + Addr: listenAddr, Net: "tcp", Handler: handler, }, @@ -63,10 +72,10 @@ func (d *dnsHandler) startServer(dnsServer *dns.Server) { } } -func (d *dnsHandler) Shutdown() error { +func (d *dnsHandler) Shutdown(ctx context.Context) error { d.logger.Info("shutting down DNS mock") for _, dnsServer := range d.dnsServer { - if err := dnsServer.Shutdown(); err != nil { + if err := dnsServer.ShutdownContext(ctx); err != nil { d.logger.Error( "failed to shutdown server", zap.Error(err), diff --git a/plugins/dns_mock/init.go b/plugins/dns_mock/init.go index a367e8a..425f083 100644 --- a/plugins/dns_mock/init.go +++ b/plugins/dns_mock/init.go @@ -3,6 +3,8 @@ package dns_mock import ( "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/logging" + "github.com/baez90/inetmock/pkg/metrics" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) @@ -10,12 +12,51 @@ const ( name = "dns_mock" ) +var ( + handlerNameLblName = "handler_name" + totalHandledRequestsCounter *prometheus.CounterVec + unhandledRequestsCounter *prometheus.CounterVec + requestDurationHistogram *prometheus.HistogramVec +) + func init() { - logger, _ := logging.CreateLogger() + var err error + var logger logging.Logger + if logger, err = logging.CreateLogger(); err != nil { + panic(err) + } logger = logger.With( - zap.String("ProtocolHandler", name), + zap.String("protocol_handler", name), ) + if totalHandledRequestsCounter, err = metrics.Counter( + name, + "handled_requests_total", + "", + handlerNameLblName, + ); err != nil { + panic(err) + } + + if unhandledRequestsCounter, err = metrics.Counter( + name, + "unhandled_requests_total", + "", + handlerNameLblName, + ); err != nil { + panic(err) + } + + if requestDurationHistogram, err = metrics.Histogram( + name, + "request_duration", + "", + nil, + handlerNameLblName, + ); err != nil { + panic(err) + } + api.Registry().RegisterHandler(name, func() api.ProtocolHandler { return &dnsHandler{ logger: logger, diff --git a/plugins/dns_mock/protocol_options.go b/plugins/dns_mock/protocol_options.go index d805eab..67b6f60 100644 --- a/plugins/dns_mock/protocol_options.go +++ b/plugins/dns_mock/protocol_options.go @@ -7,11 +7,7 @@ import ( ) const ( - rulesConfigKey = "rules" - patternConfigKey = "pattern" - responseConfigKey = "response" - fallbackStrategyConfigKey = "fallback.strategy" - fallbackArgsConfigKey = "fallback.args" + fallbackArgsConfigKey = "fallback.args" ) type resolverRule struct { @@ -24,33 +20,40 @@ type dnsOptions struct { Fallback ResolverFallback } -func loadFromConfig(config *viper.Viper) dnsOptions { - options := dnsOptions{} +func loadFromConfig(config *viper.Viper) (options dnsOptions, err error) { + type rule struct { + Pattern string + Response string + } - anonRules := config.Get(rulesConfigKey).([]interface{}) - for _, rule := range anonRules { - innerData := rule.(map[interface{}]interface{}) + type fallback struct { + Strategy string + } + + opts := struct { + Rules []rule + Fallback fallback + }{} + + err = config.Unmarshal(&opts) + + for _, rule := range opts.Rules { var err error - var compiledPattern *regexp.Regexp - var response net.IP - if compiledPattern, err = regexp.Compile(innerData[patternConfigKey].(string)); err != nil { + var rr resolverRule + if rr.pattern, err = regexp.Compile(rule.Pattern); err != nil { continue } - if response = net.ParseIP(innerData[responseConfigKey].(string)); response == nil { + if rr.response = net.ParseIP(rule.Response); rr.response == nil { continue } - - options.Rules = append(options.Rules, resolverRule{ - pattern: compiledPattern, - response: response, - }) + options.Rules = append(options.Rules, rr) } options.Fallback = CreateResolverFallback( - config.GetString(fallbackStrategyConfigKey), + opts.Fallback.Strategy, config.Sub(fallbackArgsConfigKey), ) - return options + return } diff --git a/plugins/dns_mock/regex_handler.go b/plugins/dns_mock/regex_handler.go index c32ef9d..3e72e7b 100644 --- a/plugins/dns_mock/regex_handler.go +++ b/plugins/dns_mock/regex_handler.go @@ -3,45 +3,53 @@ package dns_mock import ( "github.com/baez90/inetmock/pkg/logging" "github.com/miekg/dns" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) type regexHandler struct { - routes []resolverRule - fallback ResolverFallback - logger logging.Logger + handlerName string + routes []resolverRule + fallback ResolverFallback + logger logging.Logger } -func (r2 *regexHandler) AddRule(rule resolverRule) { - r2.routes = append(r2.routes, rule) +func (rh *regexHandler) AddRule(rule resolverRule) { + rh.routes = append(rh.routes, rule) } -func (r2 regexHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { +func (rh regexHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { + timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(rh.handlerName)) + defer func() { + timer.ObserveDuration() + }() + m := new(dns.Msg) m.Compress = false m.SetReply(r) switch r.Opcode { case dns.OpcodeQuery: - r2.handleQuery(m) + rh.handleQuery(m) } if err := w.WriteMsg(m); err != nil { - r2.logger.Error( + rh.logger.Error( "Failed to write DNS response message", zap.Error(err), ) } } -func (r2 regexHandler) handleQuery(m *dns.Msg) { +func (rh regexHandler) handleQuery(m *dns.Msg) { for _, q := range m.Question { - r2.logger.Info( + rh.logger.Info( "handling question", zap.String("question", q.Name), ) switch q.Qtype { case dns.TypeA: - for _, rule := range r2.routes { + totalHandledRequestsCounter.WithLabelValues(rh.handlerName).Inc() + for _, rule := range rh.routes { if rule.pattern.MatchString(q.Name) { m.Authoritative = true answer := &dns.A{ @@ -54,7 +62,7 @@ func (r2 regexHandler) handleQuery(m *dns.Msg) { A: rule.response, } m.Answer = append(m.Answer, answer) - r2.logger.Info( + rh.logger.Info( "matched DNS rule", zap.String("pattern", rule.pattern.String()), zap.String("response", rule.response.String()), @@ -62,13 +70,19 @@ func (r2 regexHandler) handleQuery(m *dns.Msg) { return } } - r2.handleFallbackForMessage(m, q) + rh.handleFallbackForMessage(m, q) + default: + unhandledRequestsCounter.WithLabelValues(rh.handlerName).Inc() + rh.logger.Warn( + "Unhandled DNS question type - no response will be sent", + zap.Uint16("question_type", q.Qtype), + ) } } } -func (r2 regexHandler) handleFallbackForMessage(m *dns.Msg, q dns.Question) { - fallbackIP := r2.fallback.GetIP() +func (rh regexHandler) handleFallbackForMessage(m *dns.Msg, q dns.Question) { + fallbackIP := rh.fallback.GetIP() answer := &dns.A{ Hdr: dns.RR_Header{ Name: q.Name, @@ -78,7 +92,7 @@ func (r2 regexHandler) handleFallbackForMessage(m *dns.Msg, q dns.Question) { }, A: fallbackIP, } - r2.logger.Info( + rh.logger.Info( "Falling back to generated IP", zap.String("response", fallbackIP.String()), ) diff --git a/plugins/http_mock/handler.go b/plugins/http_mock/handler.go index 75eb5f3..947e7ee 100644 --- a/plugins/http_mock/handler.go +++ b/plugins/http_mock/handler.go @@ -1,6 +1,8 @@ package http_mock import ( + "context" + "errors" "fmt" "github.com/baez90/inetmock/pkg/config" "github.com/baez90/inetmock/pkg/logging" @@ -9,34 +11,40 @@ import ( ) const ( - name = "http_mock" + name = "http_mock" + handlerNameLblName = "handler_name" + ruleMatchedLblName = "rule_matched" ) type httpHandler struct { logger logging.Logger - router *RegexpHandler server *http.Server } func (p *httpHandler) Start(config config.HandlerConfig) (err error) { options := loadFromConfig(config.Options) - addr := fmt.Sprintf("%s:%d", config.ListenAddress, config.Port) - p.server = &http.Server{Addr: addr, Handler: p.router} p.logger = p.logger.With( - zap.String("address", addr), + zap.String("handler_name", config.HandlerName), + zap.String("address", config.ListenAddr()), ) + router := &RegexpHandler{ + logger: p.logger, + handlerName: config.HandlerName, + } + p.server = &http.Server{Addr: config.ListenAddr(), Handler: router} + for _, rule := range options.Rules { - p.setupRoute(rule) + router.setupRoute(rule) } go p.startServer() return } -func (p *httpHandler) Shutdown() (err error) { +func (p *httpHandler) Shutdown(ctx context.Context) (err error) { p.logger.Info("Shutting down HTTP mock") - if err = p.server.Close(); err != nil { + if err = p.server.Shutdown(ctx); err != nil { p.logger.Error( "failed to shutdown HTTP server", zap.Error(err), @@ -50,7 +58,7 @@ func (p *httpHandler) Shutdown() (err error) { } func (p *httpHandler) startServer() { - if err := p.server.ListenAndServe(); err != nil { + if err := p.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { p.logger.Error( "failed to start http listener", zap.Error(err), diff --git a/plugins/http_mock/http_handler.go b/plugins/http_mock/http_handler.go deleted file mode 100644 index c41eb78..0000000 --- a/plugins/http_mock/http_handler.go +++ /dev/null @@ -1,38 +0,0 @@ -package http_mock - -import ( - "bytes" - "github.com/baez90/inetmock/pkg/logging" - "go.uber.org/zap" - "net/http" -) - -func (p *httpHandler) setupRoute(rule targetRule) { - p.logger.Info( - "setup routing", - zap.String("route", rule.Pattern().String()), - zap.String("response", rule.Response()), - ) - - p.router.Handler(rule.Pattern(), createHandlerForTarget(p.logger, rule.response)) -} - -func createHandlerForTarget(logger logging.Logger, targetPath string) http.Handler { - return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - headerWriter := &bytes.Buffer{} - request.Header.Write(headerWriter) - - logger.Info( - "Handling request", - zap.String("source", request.RemoteAddr), - zap.String("host", request.Host), - zap.String("method", request.Method), - zap.String("protocol", request.Proto), - zap.String("path", request.RequestURI), - zap.String("response", targetPath), - zap.Reflect("headers", request.Header), - ) - - http.ServeFile(writer, request, targetPath) - }) -} diff --git a/plugins/http_mock/init.go b/plugins/http_mock/init.go index 830f047..21929f4 100644 --- a/plugins/http_mock/init.go +++ b/plugins/http_mock/init.go @@ -3,18 +3,46 @@ package http_mock import ( "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/logging" + "github.com/baez90/inetmock/pkg/metrics" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) +var ( + totalRequestCounter *prometheus.CounterVec + requestDurationHistogram *prometheus.HistogramVec +) + func init() { - logger, _ := logging.CreateLogger() + var err error + var logger logging.Logger + if logger, err = logging.CreateLogger(); err != nil { + panic(err) + } logger = logger.With( - zap.String("ProtocolHandler", name), + zap.String("protocol_handler", name), ) + if totalRequestCounter, err = metrics.Counter( + name, + "total_requests", + "", + handlerNameLblName, + ruleMatchedLblName, + ); err != nil { + panic(err) + } + if requestDurationHistogram, err = metrics.Histogram( + name, + "request_duration", + "", + nil, + handlerNameLblName, + ); err != nil { + panic(err) + } api.Registry().RegisterHandler(name, func() api.ProtocolHandler { return &httpHandler{ logger: logger, - router: &RegexpHandler{}, } }) } diff --git a/plugins/http_mock/regex_router.go b/plugins/http_mock/regex_router.go index 2e9fcd5..b1d62fb 100644 --- a/plugins/http_mock/regex_router.go +++ b/plugins/http_mock/regex_router.go @@ -1,8 +1,13 @@ package http_mock import ( + "bytes" + "github.com/baez90/inetmock/pkg/logging" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/zap" "net/http" "regexp" + "strconv" ) type route struct { @@ -11,7 +16,9 @@ type route struct { } type RegexpHandler struct { - routes []*route + handlerName string + logger logging.Logger + routes []*route } func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) { @@ -23,12 +30,47 @@ func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.Res } func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(h.handlerName)) + defer timer.ObserveDuration() + for _, route := range h.routes { if route.pattern.MatchString(r.URL.Path) { + totalRequestCounter.WithLabelValues(h.handlerName, strconv.FormatBool(true)).Inc() route.handler.ServeHTTP(w, r) return } } // no pattern matched; send 404 response + totalRequestCounter.WithLabelValues(h.handlerName, strconv.FormatBool(false)).Inc() http.NotFound(w, r) } + +func (h *RegexpHandler) setupRoute(rule targetRule) { + h.logger.Info( + "setup routing", + zap.String("route", rule.Pattern().String()), + zap.String("response", rule.Response()), + ) + + h.Handler(rule.Pattern(), createHandlerForTarget(h.logger, rule.response)) +} + +func createHandlerForTarget(logger logging.Logger, targetPath string) http.Handler { + return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + headerWriter := &bytes.Buffer{} + request.Header.Write(headerWriter) + + logger.Info( + "Handling request", + zap.String("source", request.RemoteAddr), + zap.String("host", request.Host), + zap.String("method", request.Method), + zap.String("protocol", request.Proto), + zap.String("path", request.RequestURI), + zap.String("response", targetPath), + zap.Reflect("headers", request.Header), + ) + + http.ServeFile(writer, request, targetPath) + }) +} diff --git a/plugins/http_proxy/handler.go b/plugins/http_proxy/handler.go index 0f3f038..9ae1ae7 100644 --- a/plugins/http_proxy/handler.go +++ b/plugins/http_proxy/handler.go @@ -1,6 +1,8 @@ package http_proxy import ( + "context" + "errors" "fmt" "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/config" @@ -21,23 +23,29 @@ type httpProxy struct { } func (h *httpProxy) Start(config config.HandlerConfig) (err error) { - options := loadFromConfig(config.Options) - addr := fmt.Sprintf("%s:%d", config.ListenAddress, config.Port) - h.server = &http.Server{Addr: addr, Handler: h.proxy} + var opts httpProxyOptions + if err = config.Options.Unmarshal(&opts); err != nil { + return + } + listenAddr := config.ListenAddr() + h.server = &http.Server{Addr: listenAddr, Handler: h.proxy} h.logger = h.logger.With( - zap.String("address", addr), + zap.String("handler_name", config.HandlerName), + zap.String("address", listenAddr), ) tlsConfig := api.ServicesInstance().CertStore().TLSConfig() proxyHandler := &proxyHttpHandler{ - options: options, - logger: h.logger, + handlerName: config.HandlerName, + options: opts, + logger: h.logger, } proxyHttpsHandler := &proxyHttpsHandler{ - tlsConfig: tlsConfig, - logger: h.logger, + handlerName: config.HandlerName, + tlsConfig: tlsConfig, + logger: h.logger, } h.proxy.OnRequest().Do(proxyHandler) @@ -47,7 +55,7 @@ func (h *httpProxy) Start(config config.HandlerConfig) (err error) { } func (h *httpProxy) startProxy() { - if err := h.server.ListenAndServe(); err != nil { + if err := h.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { h.logger.Error( "failed to start proxy server", zap.Error(err), @@ -55,9 +63,9 @@ func (h *httpProxy) startProxy() { } } -func (h *httpProxy) Shutdown() (err error) { +func (h *httpProxy) Shutdown(ctx context.Context) (err error) { h.logger.Info("Shutting down HTTP proxy") - if err = h.server.Close(); err != nil { + if err = h.server.Shutdown(ctx); err != nil { h.logger.Error( "failed to shutdown proxy endpoint", zap.Error(err), diff --git a/plugins/http_proxy/init.go b/plugins/http_proxy/init.go index aa1db8f..335a9de 100644 --- a/plugins/http_proxy/init.go +++ b/plugins/http_proxy/init.go @@ -3,16 +3,41 @@ package http_proxy import ( "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/logging" + "github.com/baez90/inetmock/pkg/metrics" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "gopkg.in/elazarl/goproxy.v1" ) +var ( + handlerNameLblName = "handler_name" + totalRequestCounter *prometheus.CounterVec + totalHttpsRequestCounter *prometheus.CounterVec + requestDurationHistogram *prometheus.HistogramVec +) + func init() { - logger, _ := logging.CreateLogger() + var err error + var logger logging.Logger + if logger, err = logging.CreateLogger(); err != nil { + panic(err) + } logger = logger.With( - zap.String("ProtocolHandler", name), + zap.String("protocol_handler", name), ) + if totalRequestCounter, err = metrics.Counter(name, "total_requests", "", handlerNameLblName); err != nil { + panic(err) + } + + if requestDurationHistogram, err = metrics.Histogram(name, "request_duration", "", nil, handlerNameLblName); err != nil { + panic(err) + } + + if totalHttpsRequestCounter, err = metrics.Counter(name, "total_https_requests", "", handlerNameLblName); err != nil { + panic(err) + } + api.Registry().RegisterHandler(name, func() api.ProtocolHandler { return &httpProxy{ logger: logger, diff --git a/plugins/http_proxy/protocol_options.go b/plugins/http_proxy/protocol_options.go index 172ebcf..5ec23eb 100644 --- a/plugins/http_proxy/protocol_options.go +++ b/plugins/http_proxy/protocol_options.go @@ -2,41 +2,17 @@ package http_proxy import ( "fmt" - "github.com/spf13/viper" -) - -const ( - targetSchemeConfigKey = "target.scheme" - targetIpAddressConfigKey = "target.ipAddress" - targetPortConfigKey = "target.port" ) type redirectionTarget struct { - scheme string - ipAddress string - port uint16 + IPAddress string + Port uint16 } func (rt redirectionTarget) host() string { - return fmt.Sprintf("%s:%d", rt.ipAddress, rt.port) + return fmt.Sprintf("%s:%d", rt.IPAddress, rt.Port) } type httpProxyOptions struct { - redirectionTarget redirectionTarget -} - -func loadFromConfig(config *viper.Viper) (options httpProxyOptions) { - - config.SetDefault(targetSchemeConfigKey, "http") - config.SetDefault(targetIpAddressConfigKey, "127.0.0.1") - config.SetDefault(targetPortConfigKey, "80") - - options = httpProxyOptions{ - redirectionTarget{ - scheme: config.GetString(targetSchemeConfigKey), - ipAddress: config.GetString(targetIpAddressConfigKey), - port: uint16(config.GetInt(targetPortConfigKey)), - }, - } - return + Target redirectionTarget } diff --git a/plugins/http_proxy/protocol_options_test.go b/plugins/http_proxy/protocol_options_test.go deleted file mode 100644 index a0e2649..0000000 --- a/plugins/http_proxy/protocol_options_test.go +++ /dev/null @@ -1 +0,0 @@ -package http_proxy diff --git a/plugins/http_proxy/proxy_handler.go b/plugins/http_proxy/proxy_handler.go index 46ec1cd..1d10ba5 100644 --- a/plugins/http_proxy/proxy_handler.go +++ b/plugins/http_proxy/proxy_handler.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "github.com/baez90/inetmock/pkg/logging" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "gopkg.in/elazarl/goproxy.v1" "net/http" @@ -11,16 +12,19 @@ import ( ) type proxyHttpHandler struct { - options httpProxyOptions - logger logging.Logger + handlerName string + options httpProxyOptions + logger logging.Logger } type proxyHttpsHandler struct { - tlsConfig *tls.Config - logger logging.Logger + handlerName string + tlsConfig *tls.Config + logger logging.Logger } func (p *proxyHttpsHandler) HandleConnect(req string, _ *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { + totalHttpsRequestCounter.WithLabelValues(p.handlerName).Inc() p.logger.Info( "Intercepting HTTPS proxy request", zap.String("request", req), @@ -35,6 +39,10 @@ func (p *proxyHttpsHandler) HandleConnect(req string, _ *goproxy.ProxyCtx) (*gop } func (p *proxyHttpHandler) Handle(req *http.Request, ctx *goproxy.ProxyCtx) (retReq *http.Request, resp *http.Response) { + timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(p.handlerName)) + defer timer.ObserveDuration() + totalRequestCounter.WithLabelValues(p.handlerName).Inc() + retReq = req p.logger.Info( "Handling request", @@ -62,8 +70,7 @@ func (p proxyHttpHandler) redirectHTTPRequest(originalRequest *http.Request) (re redirectReq = &http.Request{ Method: originalRequest.Method, URL: &url.URL{ - Host: p.options.redirectionTarget.host(), - Scheme: p.options.redirectionTarget.scheme, + Host: p.options.Target.host(), Path: originalRequest.URL.Path, ForceQuery: originalRequest.URL.ForceQuery, Fragment: originalRequest.URL.Fragment, diff --git a/plugins/metrics_exporter/handler.go b/plugins/metrics_exporter/handler.go new file mode 100644 index 0000000..40dcbae --- /dev/null +++ b/plugins/metrics_exporter/handler.go @@ -0,0 +1,53 @@ +package metrics_exporter + +import ( + "context" + "errors" + "github.com/baez90/inetmock/pkg/config" + "github.com/baez90/inetmock/pkg/logging" + "github.com/prometheus/client_golang/prometheus/promhttp" + "go.uber.org/zap" + "net/http" +) + +const ( + name = "metrics_exporter" +) + +type metricsExporter struct { + logger logging.Logger + server *http.Server +} + +func (m *metricsExporter) Start(config config.HandlerConfig) (err error) { + exporterOptions := metricsExporterOptions{} + if err = config.Options.Unmarshal(&exporterOptions); err != nil { + return + } + + m.logger = m.logger.With( + zap.String("handler_name", config.HandlerName), + zap.String("address", config.ListenAddr()), + ) + + mux := http.NewServeMux() + mux.Handle(exporterOptions.Route, promhttp.Handler()) + m.server = &http.Server{ + Addr: config.ListenAddr(), + Handler: mux, + } + + go func() { + if err := m.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + m.logger.Error( + "Error occurred while serving metrics", + zap.Error(err), + ) + } + }() + return +} + +func (m *metricsExporter) Shutdown(ctx context.Context) error { + return m.server.Shutdown(ctx) +} diff --git a/plugins/metrics_exporter/init.go b/plugins/metrics_exporter/init.go new file mode 100644 index 0000000..38b06b7 --- /dev/null +++ b/plugins/metrics_exporter/init.go @@ -0,0 +1,20 @@ +package metrics_exporter + +import ( + "github.com/baez90/inetmock/pkg/api" + "github.com/baez90/inetmock/pkg/logging" + "go.uber.org/zap" +) + +func init() { + logger, _ := logging.CreateLogger() + logger = logger.With( + zap.String("protocol_handler", name), + ) + + api.Registry().RegisterHandler(name, func() api.ProtocolHandler { + return &metricsExporter{ + logger: logger, + } + }) +} diff --git a/plugins/metrics_exporter/protocol_options.go b/plugins/metrics_exporter/protocol_options.go new file mode 100644 index 0000000..89de17c --- /dev/null +++ b/plugins/metrics_exporter/protocol_options.go @@ -0,0 +1,5 @@ +package metrics_exporter + +type metricsExporterOptions struct { + Route string +} diff --git a/plugins/tls_interceptor/handler.go b/plugins/tls_interceptor/handler.go index dd91481..320a55a 100644 --- a/plugins/tls_interceptor/handler.go +++ b/plugins/tls_interceptor/handler.go @@ -1,6 +1,7 @@ package tls_interceptor import ( + "context" "crypto/tls" "fmt" "github.com/baez90/inetmock/pkg/api" @@ -8,10 +9,10 @@ import ( "github.com/baez90/inetmock/pkg/config" "github.com/baez90/inetmock/pkg/logging" "github.com/google/uuid" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "net" "sync" - "time" ) const ( @@ -19,6 +20,7 @@ const ( ) type tlsInterceptor struct { + name string options tlsOptions logger logging.Logger listener net.Listener @@ -30,15 +32,18 @@ type tlsInterceptor struct { } func (t *tlsInterceptor) Start(config config.HandlerConfig) (err error) { - t.options = loadFromConfig(config.Options) - addr := fmt.Sprintf("%s:%d", config.ListenAddress, config.Port) + t.name = config.HandlerName + if err = config.Options.Unmarshal(&config.Options); err != nil { + return + } t.logger = t.logger.With( - zap.String("address", addr), - zap.String("target", t.options.redirectionTarget.address()), + zap.String("handler_name", config.HandlerName), + zap.String("address", config.ListenAddr()), + zap.String("Target", t.options.Target.address()), ) - if t.listener, err = tls.Listen("tcp", addr, api.ServicesInstance().CertStore().TLSConfig()); err != nil { + if t.listener, err = tls.Listen("tcp", config.ListenAddr(), api.ServicesInstance().CertStore().TLSConfig()); err != nil { t.logger.Fatal( "failed to create tls listener", zap.Error(err), @@ -54,7 +59,7 @@ func (t *tlsInterceptor) Start(config config.HandlerConfig) (err error) { return } -func (t *tlsInterceptor) Shutdown() (err error) { +func (t *tlsInterceptor) Shutdown(ctx context.Context) (err error) { t.logger.Info("Shutting down TLS interceptor") t.shutdownRequested = true done := make(chan struct{}) @@ -66,7 +71,7 @@ func (t *tlsInterceptor) Shutdown() (err error) { select { case <-done: return - case <-time.After(5 * time.Second): + case <-ctx.Done(): for _, proxyConn := range t.currentConnections { if err = proxyConn.Close(); err != nil { t.logger.Error( @@ -94,19 +99,26 @@ func (t *tlsInterceptor) startListener() { continue } + handledRequestCounter.WithLabelValues(t.name).Inc() + openConnectionsGauge.WithLabelValues(t.name).Inc() t.currentConnectionsCount.Add(1) go t.proxyConn(conn) } } func (t *tlsInterceptor) proxyConn(conn net.Conn) { - defer conn.Close() - defer t.currentConnectionsCount.Done() + timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(t.name)) + defer func() { + _ = conn.Close() + t.currentConnectionsCount.Done() + openConnectionsGauge.WithLabelValues(t.name).Dec() + timer.ObserveDuration() + }() - rAddr, err := net.ResolveTCPAddr("tcp", t.options.redirectionTarget.address()) + rAddr, err := net.ResolveTCPAddr("tcp", t.options.Target.address()) if err != nil { t.logger.Error( - "failed to resolve proxy target", + "failed to resolve proxy Target", zap.Error(err), ) } @@ -114,7 +126,7 @@ func (t *tlsInterceptor) proxyConn(conn net.Conn) { targetConn, err := net.DialTCP("tcp", nil, rAddr) if err != nil { t.logger.Error( - "failed to connect to proxy target", + "failed to connect to proxy Target", zap.Error(err), ) return diff --git a/plugins/tls_interceptor/init.go b/plugins/tls_interceptor/init.go index 054c276..c063707 100644 --- a/plugins/tls_interceptor/init.go +++ b/plugins/tls_interceptor/init.go @@ -3,17 +3,40 @@ package tls_interceptor import ( "github.com/baez90/inetmock/pkg/api" "github.com/baez90/inetmock/pkg/logging" + "github.com/baez90/inetmock/pkg/metrics" "github.com/google/uuid" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "sync" ) +var ( + labelNames = []string{"handler_name"} + handledRequestCounter *prometheus.CounterVec + openConnectionsGauge *prometheus.GaugeVec + requestDurationHistogram *prometheus.HistogramVec +) + func init() { - logger, _ := logging.CreateLogger() + var err error + var logger logging.Logger + if logger, err = logging.CreateLogger(); err != nil { + panic(err) + } logger = logger.With( - zap.String("ProtocolHandler", name), + zap.String("protocol_handler", name), ) + if handledRequestCounter, err = metrics.Counter(name, "handled_requests", "", labelNames...); err != nil { + panic(err) + } + if openConnectionsGauge, err = metrics.Gauge(name, "open_connections", "", labelNames...); err != nil { + panic(err) + } + if requestDurationHistogram, err = metrics.Histogram(name, "request_duration", "", nil, labelNames...); err != nil { + panic(err) + } + api.Registry().RegisterHandler(name, func() api.ProtocolHandler { return &tlsInterceptor{ logger: logger, diff --git a/plugins/tls_interceptor/protocol_options.go b/plugins/tls_interceptor/protocol_options.go index 62d1bf5..097ec28 100644 --- a/plugins/tls_interceptor/protocol_options.go +++ b/plugins/tls_interceptor/protocol_options.go @@ -2,32 +2,17 @@ package tls_interceptor import ( "fmt" - "github.com/spf13/viper" -) - -const ( - targetIpAddressConfigKey = "target.ipAddress" - targetPortConfigKey = "target.port" ) type redirectionTarget struct { - ipAddress string - port uint16 + IPAddress string + Port uint16 } func (rt redirectionTarget) address() string { - return fmt.Sprintf("%s:%d", rt.ipAddress, rt.port) + return fmt.Sprintf("%s:%d", rt.IPAddress, rt.Port) } type tlsOptions struct { - redirectionTarget redirectionTarget -} - -func loadFromConfig(config *viper.Viper) tlsOptions { - return tlsOptions{ - redirectionTarget: redirectionTarget{ - ipAddress: config.GetString(targetIpAddressConfigKey), - port: uint16(config.GetInt(targetPortConfigKey)), - }, - } + Target redirectionTarget } diff --git a/plugins/tls_interceptor/proxy.go b/plugins/tls_interceptor/proxy.go index 46b8207..1b214cc 100644 --- a/plugins/tls_interceptor/proxy.go +++ b/plugins/tls_interceptor/proxy.go @@ -2,14 +2,22 @@ package tls_interceptor import ( "net" + "sync" +) + +var ( + bufferPool = sync.Pool{ + New: func() interface{} { + return make([]byte, 1024) + }, + } ) func chanFromConn(conn net.Conn) chan []byte { c := make(chan []byte) go func() { - b := make([]byte, 1024) - + b := bufferPool.Get().([]byte) for { n, err := conn.Read(b) if n > 0 { diff --git a/plugins/tls_interceptor/proxy_conn.go b/plugins/tls_interceptor/proxy_conn.go index 285f991..f7529d9 100644 --- a/plugins/tls_interceptor/proxy_conn.go +++ b/plugins/tls_interceptor/proxy_conn.go @@ -13,7 +13,7 @@ type proxyConn struct { func (p *proxyConn) Close() error { var err error if targetErr := p.target.Close(); targetErr != nil { - err = fmt.Errorf("error while closing target conn: %w", targetErr) + err = fmt.Errorf("error while closing Target conn: %w", targetErr) } if sourceErr := p.source.Close(); sourceErr != nil { err = fmt.Errorf("error while closing source conn: %w", err)