Skip to content

Commit

Permalink
Add retries count arg, move retry logic into DownloadGeoLite2DB function
Browse files Browse the repository at this point in the history
Signed-off-by: Sergey Shakuto <[email protected]>
  • Loading branch information
Sergey Shakuto committed Jun 29, 2021
1 parent 9a5a1bd commit bffb372
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 51 deletions.
45 changes: 4 additions & 41 deletions cmd/nginx/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -181,7 +177,8 @@ Takes the form "<host>: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")

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cmd/nginx/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
63 changes: 55 additions & 8 deletions internal/nginx/maxmind.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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 {
Expand Down

0 comments on commit bffb372

Please sign in to comment.