From 1698bb89c0d3764295c37ede72ea61b724019502 Mon Sep 17 00:00:00 2001 From: Sergey Shakuto Date: Mon, 14 Jun 2021 16:32:04 +0300 Subject: [PATCH 1/4] Retry to download maxmind DB if it fails. Signed-off-by: Sergey Shakuto --- cmd/nginx/flags.go | 52 +++++++++++++++++++++++++++----- cmd/nginx/flags_test.go | 13 ++++++++ docs/user-guide/cli-arguments.md | 1 + go.mod | 3 +- go.sum | 28 +++++++++++++++++ internal/nginx/maxmind.go | 4 +++ 6 files changed, 93 insertions(+), 8 deletions(-) diff --git a/cmd/nginx/flags.go b/cmd/nginx/flags.go index 5fb63b4302..c49f4208d7 100644 --- a/cmd/nginx/flags.go +++ b/cmd/nginx/flags.go @@ -19,14 +19,15 @@ package main import ( "flag" "fmt" + "net" + "net/url" "os" + "syscall" "time" "github.com/spf13/pflag" - apiv1 "k8s.io/api/core/v1" - "k8s.io/klog/v2" - + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/ingress-nginx/internal/ingress/annotations/class" "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/controller" @@ -34,6 +35,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/status" ing_net "k8s.io/ingress-nginx/internal/net" "k8s.io/ingress-nginx/internal/nginx" + klog "k8s.io/klog/v2" ) func parseFlags() (bool, *controller.Configuration, error) { @@ -179,6 +181,7 @@ Takes the form ":port". If not provided, no admission controller is starte flags.StringVar(&nginx.MaxmindLicenseKey, "maxmind-license-key", "", `Maxmind license key to download GeoLite2 Databases. https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases`) flags.StringVar(&nginx.MaxmindEditionIDs, "maxmind-edition-ids", "GeoLite2-City,GeoLite2-ASN", `Maxmind edition ids to download GeoLite2 Databases.`) + flags.DurationVar(&nginx.MaxmindRetriesTimeout, "maxmind-retries-timeout", time.Second*0, "Maxmind downloading delay between 1st and 2nd attempt (5 attempts in total), 0s - do not retry to download if something went wrong.") flag.Set("logtostderr", "true") @@ -303,16 +306,51 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g config.RootCAFile = *rootCAFile } + var err error if (nginx.MaxmindLicenseKey != "" || nginx.MaxmindMirror != "") && nginx.MaxmindEditionIDs != "" { - if err := nginx.ValidateGeoLite2DBEditions(); err != nil { + if err = nginx.ValidateGeoLite2DBEditions(); err != nil { return false, nil, err } - klog.InfoS("downloading maxmind GeoIP2 databases") - if err := nginx.DownloadGeoLite2DB(); err != nil { + klog.InfoS("trying to download maxmind GeoIP2 databases...") + defaultRetry := wait.Backoff{ + Steps: 5, + Duration: nginx.MaxmindRetriesTimeout, + Factor: 1.5, + Jitter: 0.1, + } + if nginx.MaxmindRetriesTimeout == time.Duration(0) { + defaultRetry.Steps = 1 + } + + var lastErr error + retries := 0 + + err = wait.ExponentialBackoff(defaultRetry, func() (bool, error) { + err := nginx.DownloadGeoLite2DB() + lastErr = err + if err == nil { + return true, nil + } + + if e, ok := err.(*url.Error); ok { + if e, ok := e.Err.(*net.OpError); ok { + if e, ok := e.Err.(*os.SyscallError); ok { + if e.Err == syscall.ECONNREFUSED { + retries++ + klog.InfoS("download failed on attempt " + fmt.Sprint(retries)) + return false, nil + } + } + } + } + return true, nil + }) + err = lastErr + if err != nil { klog.ErrorS(err, "unexpected error downloading GeoIP2 database") } config.MaxmindEditionFiles = nginx.MaxmindEditionFiles } - return false, config, nil + return false, config, err } diff --git a/cmd/nginx/flags_test.go b/cmd/nginx/flags_test.go index 4286d4a20d..8cd64435a9 100644 --- a/cmd/nginx/flags_test.go +++ b/cmd/nginx/flags_test.go @@ -105,3 +105,16 @@ func TestMaxmindMirror(t *testing.T) { t.Fatalf("Expected an error parsing flags but none returned") } } + +func TestMaxmindRetryDownload(t *testing.T) { + resetForTesting(func() { t.Fatal("Parsing failed") }) + + oldArgs := os.Args + defer func() { os.Args = oldArgs }() + os.Args = []string{"cmd", "--publish-service", "namespace/test", "--http-port", "0", "--https-port", "0", "--maxmind-mirror", "http://127.0.0.1", "--maxmind-license-key", "0000000", "--maxmind-edition-ids", "GeoLite2-City", "--maxmind-retries-timeout", "1s"} + + _, _, err := parseFlags() + if err == nil { + t.Fatalf("Expected an error parsing flags but none returned") + } +} diff --git a/docs/user-guide/cli-arguments.md b/docs/user-guide/cli-arguments.md index 799ce73243..33227abc30 100644 --- a/docs/user-guide/cli-arguments.md +++ b/docs/user-guide/cli-arguments.md @@ -33,6 +33,7 @@ They are set in the container spec of the `nginx-ingress-controller` Deployment | `--log_file_max_size` | Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) | | `--logtostderr` | log to standard error instead of files (default true) | | `--maxmind-edition-ids` | Maxmind edition ids to download GeoLite2 Databases. (default "GeoLite2-City,GeoLite2-ASN") | +| `--maxmind-retries-timeout` | "Maxmind downloading delay between 1st and 2nd attempt (5 attempts in total), 0s - do not retry to download if something went wrong. (default 0s) | | `--maxmind-license-key` | Maxmind license key to download GeoLite2 Databases. https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases | | `--metrics-per-host` | Export metrics per-host (default true) | | `--profiler-port` | Port to use for expose the ingress controller Go profiler when it is enabled. (default 10245) | diff --git a/go.mod b/go.mod index efbf04769e..de3c2f3493 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/mitchellh/mapstructure v1.3.2 github.com/moul/pb v0.0.0-20180404114147-54bdd96e6a52 github.com/ncabatoff/process-exporter v0.7.2 - github.com/onsi/ginkgo v1.14.1 + github.com/onsi/ginkgo v1.16.4 github.com/opencontainers/runc v1.0.0-rc92 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 @@ -45,4 +45,5 @@ require ( k8s.io/utils v0.0.0-20201110183641-67b214c5f920 pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732 sigs.k8s.io/controller-runtime v0.8.0 + sigs.k8s.io/kind v0.11.1 // indirect ) diff --git a/go.sum b/go.sum index 4439cb7374..a6f8e4e857 100644 --- a/go.sum +++ b/go.sum @@ -62,6 +62,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -154,6 +156,8 @@ github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5I github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq2lumco= +github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fasthttp/websocket v1.4.2 h1:AU/zSiIIAuJjBMf5o+vO0syGOnEfvZRu40xIhW/3RuM= github.com/fasthttp/websocket v1.4.2/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -203,6 +207,8 @@ github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tF github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -336,6 +342,7 @@ github.com/imkira/go-interpol v1.0.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/C github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -391,6 +398,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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= @@ -448,6 +457,8 @@ github.com/ncabatoff/process-exporter v0.7.2 h1:2UxJJ5fm9fiiUHqHgbusrfceCFQpEET/ github.com/ncabatoff/process-exporter v0.7.2/go.mod h1:d7Yf/brhprE2fjCdtZ2Edt0so30RY5PmtRu6qD0gUOc= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -460,6 +471,8 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -486,6 +499,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +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/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -625,6 +640,7 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDf github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zakjan/cert-chain-resolver v0.0.0-20200729110141-6b99e360f97a h1:Tj7Mkjj6sjeNwFBiRHM7ieg1CiPHCDNSMSmS0ooGcZo= github.com/zakjan/cert-chain-resolver v0.0.0-20200729110141-6b99e360f97a/go.mod h1:KNkcm66cr4ilOiEcjydK+tc2ShPUhqmuoXCljXUBPu8= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -739,6 +755,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -755,6 +772,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -786,6 +804,7 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -804,6 +823,9 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/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= @@ -865,6 +887,8 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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= @@ -982,6 +1006,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1038,6 +1064,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.8.0 h1:s0dYdo7lQgJiAf+alP82PRwbz+oAqL3oSyMQ18XRDOc= sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4= +sigs.k8s.io/kind v0.11.1 h1:pVzOkhUwMBrCB0Q/WllQDO3v14Y+o2V0tFgjTqIUjwA= +sigs.k8s.io/kind v0.11.1/go.mod h1:fRpgVhtqAWrtLB9ED7zQahUimpUXuG/iHT88xYqEGIA= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= diff --git a/internal/nginx/maxmind.go b/internal/nginx/maxmind.go index 0f3c370166..122c3966fd 100644 --- a/internal/nginx/maxmind.go +++ b/internal/nginx/maxmind.go @@ -25,6 +25,7 @@ import ( "os" "path" "strings" + "time" ) // MaxmindLicenseKey maxmind license key to download databases @@ -39,6 +40,9 @@ var MaxmindEditionFiles []string // MaxmindMirror maxmind database mirror url (http://geoip.local) var MaxmindMirror = "" +// MaxmindRetriesTimeout maxmind download retries timeout in seconds, 0 - do not retry to download if something went wrong +var MaxmindRetriesTimeout = time.Second * 0 + const ( geoIPPath = "/etc/nginx/geoip" dbExtension = ".mmdb" From bffb372620166a5afa678f3f1ee3f65af08a46c1 Mon Sep 17 00:00:00 2001 From: Sergey Shakuto Date: Tue, 29 Jun 2021 17:43:42 +0300 Subject: [PATCH 2/4] Add retries count arg, move retry logic into DownloadGeoLite2DB function Signed-off-by: Sergey Shakuto --- cmd/nginx/flags.go | 45 ++--------------------- cmd/nginx/flags_test.go | 2 +- docs/user-guide/cli-arguments.md | 3 +- internal/nginx/maxmind.go | 63 ++++++++++++++++++++++++++++---- 4 files changed, 62 insertions(+), 51 deletions(-) diff --git a/cmd/nginx/flags.go b/cmd/nginx/flags.go index c49f4208d7..c46aa9cbbc 100644 --- a/cmd/nginx/flags.go +++ b/cmd/nginx/flags.go @@ -19,15 +19,11 @@ package main import ( "flag" "fmt" - "net" - "net/url" "os" - "syscall" "time" "github.com/spf13/pflag" apiv1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/ingress-nginx/internal/ingress/annotations/class" "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/controller" @@ -181,7 +177,8 @@ Takes the form ":port". If not provided, no admission controller is starte flags.StringVar(&nginx.MaxmindLicenseKey, "maxmind-license-key", "", `Maxmind license key to download GeoLite2 Databases. https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases`) flags.StringVar(&nginx.MaxmindEditionIDs, "maxmind-edition-ids", "GeoLite2-City,GeoLite2-ASN", `Maxmind edition ids to download GeoLite2 Databases.`) - flags.DurationVar(&nginx.MaxmindRetriesTimeout, "maxmind-retries-timeout", time.Second*0, "Maxmind downloading delay between 1st and 2nd attempt (5 attempts in total), 0s - do not retry to download if something went wrong.") + flags.IntVar(&nginx.MaxmindRetriesCount, "maxmind-retries-count", 1, "Number of attempts to download the GeoIP DB.") + flags.DurationVar(&nginx.MaxmindRetriesTimeout, "maxmind-retries-timeout", time.Second*0, "Maxmind downloading delay between 1st and 2nd attempt, 0s - do not retry to download if something went wrong.") flag.Set("logtostderr", "true") @@ -311,42 +308,8 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g if err = nginx.ValidateGeoLite2DBEditions(); err != nil { return false, nil, err } - klog.InfoS("trying to download maxmind GeoIP2 databases...") - defaultRetry := wait.Backoff{ - Steps: 5, - Duration: nginx.MaxmindRetriesTimeout, - Factor: 1.5, - Jitter: 0.1, - } - if nginx.MaxmindRetriesTimeout == time.Duration(0) { - defaultRetry.Steps = 1 - } - - var lastErr error - retries := 0 - - err = wait.ExponentialBackoff(defaultRetry, func() (bool, error) { - err := nginx.DownloadGeoLite2DB() - lastErr = err - if err == nil { - return true, nil - } - - if e, ok := err.(*url.Error); ok { - if e, ok := e.Err.(*net.OpError); ok { - if e, ok := e.Err.(*os.SyscallError); ok { - if e.Err == syscall.ECONNREFUSED { - retries++ - klog.InfoS("download failed on attempt " + fmt.Sprint(retries)) - return false, nil - } - } - } - } - return true, nil - }) - err = lastErr - if err != nil { + klog.InfoS("downloading maxmind GeoIP2 databases") + if err = nginx.DownloadGeoLite2DB(nginx.MaxmindRetriesTimeout, nginx.MaxmindRetriesCount); err != nil { klog.ErrorS(err, "unexpected error downloading GeoIP2 database") } config.MaxmindEditionFiles = nginx.MaxmindEditionFiles diff --git a/cmd/nginx/flags_test.go b/cmd/nginx/flags_test.go index 8cd64435a9..b25fa75570 100644 --- a/cmd/nginx/flags_test.go +++ b/cmd/nginx/flags_test.go @@ -111,7 +111,7 @@ func TestMaxmindRetryDownload(t *testing.T) { oldArgs := os.Args defer func() { os.Args = oldArgs }() - os.Args = []string{"cmd", "--publish-service", "namespace/test", "--http-port", "0", "--https-port", "0", "--maxmind-mirror", "http://127.0.0.1", "--maxmind-license-key", "0000000", "--maxmind-edition-ids", "GeoLite2-City", "--maxmind-retries-timeout", "1s"} + os.Args = []string{"cmd", "--publish-service", "namespace/test", "--http-port", "0", "--https-port", "0", "--maxmind-mirror", "http://127.0.0.1", "--maxmind-license-key", "0000000", "--maxmind-edition-ids", "GeoLite2-City", "--maxmind-retries-timeout", "1s", "--maxmind-retries-count", "3"} _, _, err := parseFlags() if err == nil { diff --git a/docs/user-guide/cli-arguments.md b/docs/user-guide/cli-arguments.md index 33227abc30..d51c759944 100644 --- a/docs/user-guide/cli-arguments.md +++ b/docs/user-guide/cli-arguments.md @@ -33,7 +33,8 @@ They are set in the container spec of the `nginx-ingress-controller` Deployment | `--log_file_max_size` | Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) | | `--logtostderr` | log to standard error instead of files (default true) | | `--maxmind-edition-ids` | Maxmind edition ids to download GeoLite2 Databases. (default "GeoLite2-City,GeoLite2-ASN") | -| `--maxmind-retries-timeout` | "Maxmind downloading delay between 1st and 2nd attempt (5 attempts in total), 0s - do not retry to download if something went wrong. (default 0s) | +| `--maxmind-retries-timeout` | Maxmind downloading delay between 1st and 2nd attempt, 0s - do not retry to download if something went wrong. (default 0s) | +| `--maxmind-retries-count` | Number of attempts to download the GeoIP DB. (default 1) | | `--maxmind-license-key` | Maxmind license key to download GeoLite2 Databases. https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases | | `--metrics-per-host` | Export metrics per-host (default true) | | `--profiler-port` | Port to use for expose the ingress controller Go profiler when it is enabled. (default 10245) | diff --git a/internal/nginx/maxmind.go b/internal/nginx/maxmind.go index 122c3966fd..94506f88ab 100644 --- a/internal/nginx/maxmind.go +++ b/internal/nginx/maxmind.go @@ -21,11 +21,17 @@ import ( "compress/gzip" "fmt" "io" + "net" "net/http" + "net/url" "os" "path" "strings" + "syscall" "time" + + "k8s.io/apimachinery/pkg/util/wait" + klog "k8s.io/klog/v2" ) // MaxmindLicenseKey maxmind license key to download databases @@ -40,6 +46,9 @@ var MaxmindEditionFiles []string // MaxmindMirror maxmind database mirror url (http://geoip.local) var MaxmindMirror = "" +// MaxmindRetriesCount number of attempts to download the GeoIP DB +var MaxmindRetriesCount = 1 + // MaxmindRetriesTimeout maxmind download retries timeout in seconds, 0 - do not retry to download if something went wrong var MaxmindRetriesTimeout = time.Second * 0 @@ -64,15 +73,53 @@ func GeoLite2DBExists() bool { // DownloadGeoLite2DB downloads the required databases by the // GeoIP2 NGINX module using a license key from MaxMind. -func DownloadGeoLite2DB() error { - for _, dbName := range strings.Split(MaxmindEditionIDs, ",") { - err := downloadDatabase(dbName) - if err != nil { - return err - } - MaxmindEditionFiles = append(MaxmindEditionFiles, dbName+dbExtension) +func DownloadGeoLite2DB(period time.Duration, attempts int) error { + if attempts < 1 { + attempts = 1 } - return nil + + defaultRetry := wait.Backoff{ + Steps: attempts, + Duration: period, + Factor: 1.5, + Jitter: 0.1, + } + if period == time.Duration(0) { + defaultRetry.Steps = 1 + } + + var lastErr error + retries := 0 + + _ = wait.ExponentialBackoff(defaultRetry, func() (bool, error) { + var dlError error + for _, dbName := range strings.Split(MaxmindEditionIDs, ",") { + dlError = downloadDatabase(dbName) + if dlError != nil { + break + } + MaxmindEditionFiles = append(MaxmindEditionFiles, dbName+dbExtension) + } + + lastErr = dlError + if dlError == nil { + return true, nil + } + + if e, ok := dlError.(*url.Error); ok { + if e, ok := e.Err.(*net.OpError); ok { + if e, ok := e.Err.(*os.SyscallError); ok { + if e.Err == syscall.ECONNREFUSED { + retries++ + klog.InfoS("download failed on attempt " + fmt.Sprint(retries)) + return false, nil + } + } + } + } + return true, nil + }) + return lastErr } func createURL(mirror, licenseKey, dbName string) string { From 6094cc88d83ec1fc57700248903c0718fe826e51 Mon Sep 17 00:00:00 2001 From: Sergey Shakuto Date: Wed, 30 Jun 2021 15:54:28 +0300 Subject: [PATCH 3/4] Reorder parameters in DownloadGeoLite2DB Signed-off-by: Sergey Shakuto --- cmd/nginx/flags.go | 2 +- internal/nginx/maxmind.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nginx/flags.go b/cmd/nginx/flags.go index c46aa9cbbc..57efcf1ea9 100644 --- a/cmd/nginx/flags.go +++ b/cmd/nginx/flags.go @@ -309,7 +309,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g return false, nil, err } klog.InfoS("downloading maxmind GeoIP2 databases") - if err = nginx.DownloadGeoLite2DB(nginx.MaxmindRetriesTimeout, nginx.MaxmindRetriesCount); err != nil { + if err = nginx.DownloadGeoLite2DB(nginx.MaxmindRetriesCount, nginx.MaxmindRetriesTimeout); err != nil { klog.ErrorS(err, "unexpected error downloading GeoIP2 database") } config.MaxmindEditionFiles = nginx.MaxmindEditionFiles diff --git a/internal/nginx/maxmind.go b/internal/nginx/maxmind.go index 94506f88ab..097e55e996 100644 --- a/internal/nginx/maxmind.go +++ b/internal/nginx/maxmind.go @@ -73,7 +73,7 @@ func GeoLite2DBExists() bool { // DownloadGeoLite2DB downloads the required databases by the // GeoIP2 NGINX module using a license key from MaxMind. -func DownloadGeoLite2DB(period time.Duration, attempts int) error { +func DownloadGeoLite2DB(attempts int, period time.Duration) error { if attempts < 1 { attempts = 1 } From cbfc5ef42b48fed87c6b0a9cfc84e38b3cd8d063 Mon Sep 17 00:00:00 2001 From: Sergey Shakuto Date: Thu, 1 Jul 2021 14:09:48 +0300 Subject: [PATCH 4/4] Remove hardcoded value Signed-off-by: Sergey Shakuto --- internal/nginx/maxmind.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/nginx/maxmind.go b/internal/nginx/maxmind.go index 097e55e996..c764be1615 100644 --- a/internal/nginx/maxmind.go +++ b/internal/nginx/maxmind.go @@ -52,6 +52,9 @@ var MaxmindRetriesCount = 1 // MaxmindRetriesTimeout maxmind download retries timeout in seconds, 0 - do not retry to download if something went wrong var MaxmindRetriesTimeout = time.Second * 0 +// minimumRetriesCount minimum value of the MaxmindRetriesCount parameter. If MaxmindRetriesCount less than minimumRetriesCount, it will be set to minimumRetriesCount +const minimumRetriesCount = 1 + const ( geoIPPath = "/etc/nginx/geoip" dbExtension = ".mmdb" @@ -74,8 +77,8 @@ func GeoLite2DBExists() bool { // DownloadGeoLite2DB downloads the required databases by the // GeoIP2 NGINX module using a license key from MaxMind. func DownloadGeoLite2DB(attempts int, period time.Duration) error { - if attempts < 1 { - attempts = 1 + if attempts < minimumRetriesCount { + attempts = minimumRetriesCount } defaultRetry := wait.Backoff{ @@ -85,7 +88,7 @@ func DownloadGeoLite2DB(attempts int, period time.Duration) error { Jitter: 0.1, } if period == time.Duration(0) { - defaultRetry.Steps = 1 + defaultRetry.Steps = minimumRetriesCount } var lastErr error