Hello community, here is the log from the commit of package geoipupdate for openSUSE:Factory checked in at 2020-11-05 21:54:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/geoipupdate (Old) and /work/SRC/openSUSE:Factory/.geoipupdate.new.11331 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "geoipupdate" Thu Nov 5 21:54:47 2020 rev:14 rq:846049 version:4.5.0 Changes: -------- --- /work/SRC/openSUSE:Factory/geoipupdate/geoipupdate.changes 2020-05-07 14:56:35.246519254 +0200 +++ /work/SRC/openSUSE:Factory/.geoipupdate.new.11331/geoipupdate.changes 2020-11-05 21:55:33.080099001 +0100 @@ -1,0 +2,21 @@ +Wed Nov 4 15:54:26 UTC 2020 - Paolo Stivanin <i...@paolostivanin.com> + +- Update to version 4.5.0: +* We no longer use a third party library for exponential backoff +* The edition ID is now included when there is a failure retrieving + a database +* The Docker image no longer prints the generated GeoIP.conf when + starting up. This prevents a possible leak of the account's + license key +* The minimum Go version is now 1.11. +* Failing HTTP requests are now retried using an exponential backoff. + The period to keep retrying any failed request is set to 5 minutes + by default and can be adjusted using the new RetryFor + configuration option. +* When using the go package rather than the command-line tool, the + null value for RetryFor will be 0 seconds, which means no retries + will be performed. To change that, set RetryFor explicitly in the + Config you provide, or obtain your Config value via + geoipupdate.NewConfig. + +------------------------------------------------------------------- Old: ---- geoipupdate-4.3.0.tar.gz New: ---- geoipupdate-4.5.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ geoipupdate.spec ++++++ --- /var/tmp/diff_new_pack.NgjoXk/_old 2020-11-05 21:55:33.888097185 +0100 +++ /var/tmp/diff_new_pack.NgjoXk/_new 2020-11-05 21:55:33.892097176 +0100 @@ -18,7 +18,7 @@ # Common info Name: geoipupdate -Version: 4.3.0 +Version: 4.5.0 Release: 0 Summary: GeoIP update client code License: Apache-2.0 OR MIT @@ -33,7 +33,7 @@ Patch0: disable-pandoc.patch %if 0%{?suse_version} >= 1500 # Build-time parameters -BuildRequires: go >= 1.10 +BuildRequires: go >= 1.11 # Manpage BuildRequires: perl%{?suse_version:-base} %endif ++++++ _service ++++++ --- /var/tmp/diff_new_pack.NgjoXk/_old 2020-11-05 21:55:33.952097041 +0100 +++ /var/tmp/diff_new_pack.NgjoXk/_new 2020-11-05 21:55:33.952097041 +0100 @@ -2,7 +2,7 @@ <service name="tar_scm" mode="disabled"> <param name="scm">git</param> <param name="url">git://github.com/maxmind/geoipupdate</param> - <param name="revision">v4.3.0</param> + <param name="revision">v4.5.0</param> <param name="exclude">.git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.NgjoXk/_old 2020-11-05 21:55:33.976096987 +0100 +++ /var/tmp/diff_new_pack.NgjoXk/_new 2020-11-05 21:55:33.976096987 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">git://github.com/maxmind/geoipupdate</param> - <param name="changesrevision">09ac4548fd9311541cb0885e361eb57804b7b781</param> + <param name="changesrevision">65d57e3edea7798cd72adaafca50e96f34a61d59</param> </service> </servicedata> ++++++ geoipupdate-4.3.0.tar.gz -> geoipupdate-4.5.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/.github/workflows/codeql-analysis.yml new/geoipupdate-4.5.0/.github/workflows/codeql-analysis.yml --- old/geoipupdate-4.3.0/.github/workflows/codeql-analysis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/geoipupdate-4.5.0/.github/workflows/codeql-analysis.yml 2020-10-28 22:03:38.000000000 +0100 @@ -0,0 +1,51 @@ +name: "Code scanning - action" + +on: + push: + pull_request: + schedule: + - cron: '0 11 * * 2' + +jobs: + CodeQL-Build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/.github/workflows/go.yml new/geoipupdate-4.5.0/.github/workflows/go.yml --- old/geoipupdate-4.3.0/.github/workflows/go.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/geoipupdate-4.5.0/.github/workflows/go.yml 2020-10-28 22:03:38.000000000 +0100 @@ -0,0 +1,37 @@ +name: Go + +on: + push: + pull_request: + schedule: + - cron: '5 10 * * SUN' + +jobs: + + build: + strategy: + matrix: + # We test back to 1.11 as we need to support old, EOL'd Go versions + # to build PPA packages for older versions of Ubuntu. + go-version: [1.11.x, 1.12.x, 1.13.x, 1.14.x, 1.15.x] + platform: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.platform }} + name: "Build ${{ matrix.go-version }} test on ${{ matrix.platform }}" + steps: + - name: Set up Go 1.x + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Get dependencies + run: go get -v -t -d ./... + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -race -v ./... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/.github/workflows/golangci-lint.yml new/geoipupdate-4.5.0/.github/workflows/golangci-lint.yml --- old/geoipupdate-4.3.0/.github/workflows/golangci-lint.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/geoipupdate-4.5.0/.github/workflows/golangci-lint.yml 2020-10-28 22:03:38.000000000 +0100 @@ -0,0 +1,18 @@ +name: golangci-lint + +on: + push: + pull_request: + schedule: + - cron: '5 5 * * SUN' + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/.golangci.toml new/geoipupdate-4.5.0/.golangci.toml --- old/geoipupdate-4.3.0/.golangci.toml 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/.golangci.toml 2020-10-28 22:03:38.000000000 +0100 @@ -5,34 +5,68 @@ [linters] disable-all = true enable = [ + "bodyclose", "deadcode", "depguard", "errcheck", + "exhaustive", + "exportloopref", "goconst", "gocyclo", "gocritic", - "gofmt", + "gofumpt", "golint", "gosec", "gosimple", + "govet", "ineffassign", + "lll", "maligned", "misspell", "nakedret", + "noctx", + "nolintlint", + # https://github.com/golangci/golangci-lint/issues/287 + # "safesql", + "sqlclosecheck", "staticcheck", "structcheck", + "stylecheck", "typecheck", "unconvert", "unparam", + "unused", "varcheck", - "vet", "vetshadow", ] -# This goes off for MD5 usage, which we use heavily -[[issues.exclude-rules]] -text = "weak cryptographic primitive" -linters = ["gosec"] +[linters-settings.errcheck] + # Ignoring Close so that we don't have to have a bunch of + # `defer func() { _ = r.Close() }()` constructs when we + # don't actually care about the error. + ignore = "Close,fmt:.*" + +[linters-settings.exhaustive] + default-signifies-exhaustive = true + +[linters-settings.gofumpt] + extra-rules = true + +[linters-settings.lll] + line-length = 120 + tab-width = 4 [issues] exclude-use-default = false + + [[issues.exclude-rules]] + linters = [ + "gosec" + ] + # G306 - "Expect WriteFile permissions to be 0600 or less". + text = "G306" + + # This goes off for MD5 usage, which we use heavily + [[issues.exclude-rules]] + text = "weak cryptographic primitive" + linters = ["gosec"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/.travis.yml new/geoipupdate-4.5.0/.travis.yml --- old/geoipupdate-4.3.0/.travis.yml 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,33 +0,0 @@ -language: go - -os: - - linux - - osx - - windows - -go: - - "1.10.x" - - "1.11.x" - - "1.12.x" - - "1.13.x" - - "1.14.x" - -before_script: - - | - if [[ $TRAVIS_GO_VERSION == '1.10.x' ]]; then - go get -t -u ./... - fi - - | - if [[ $TRAVIS_GO_VERSION == '1.14.x' && $TRAVIS_OS_NAME == 'linux' ]]; then - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin - fi - -script: - - go test -v -race ./... - - | - if [[ $TRAVIS_GO_VERSION == '1.14.x' && $TRAVIS_OS_NAME == 'linux' ]]; then - golangci-lint run - fi - -env: - - GO111MODULE=on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/CHANGELOG.md new/geoipupdate-4.5.0/CHANGELOG.md --- old/geoipupdate-4.3.0/CHANGELOG.md 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/CHANGELOG.md 2020-10-28 22:03:38.000000000 +0100 @@ -1,5 +1,26 @@ # CHANGELOG +## 4.5.0 (2020-10-28) + +* We no longer use a third party library for exponential backoff. This + restores support for older Go versions. + +## 4.4.0 (2020-10-28) + +* The edition ID is now included when there is a failure retrieving a + database. +* The Docker image no longer prints the generated `GeoIP.conf` when starting + up. This prevents a possible leak of the account's license key. Pull + request by Nate Gay. GitHub #109. +* The minimum Go version is now 1.11. +* Failing HTTP requests are now retried using an exponential backoff. The + period to keep retrying any failed request is set to 5 minutes by default and + can be adjusted using the new `RetryFor` configuration option. +* When using the go package rather than the command-line tool, the null value + for `RetryFor` will be 0 seconds, which means no retries will be performed. To + change that, set `RetryFor` explicitly in the `Config` you provide, or obtain + your `Config` value via `geoipupdate.NewConfig`. + ## 4.3.0 (2020-04-16) * First release to Docker Hub. Requested by Shun Yanaura. GitHub #24. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/README.md new/geoipupdate-4.5.0/README.md --- old/geoipupdate-4.3.0/README.md 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/README.md 2020-10-28 22:03:38.000000000 +0100 @@ -1,7 +1,5 @@ # GeoIP Update -[![Build Status](https://travis-ci.com/maxmind/geoipupdate.svg?branch=master)](https://travis-ci.com/maxmind/geoipupdate) - The GeoIP Update program performs automatic updates of GeoIP2 and GeoIP Legacy binary databases. CSV databases are _not_ supported. @@ -70,7 +68,7 @@ Download the appropriate .rpm for your system. -Run `rpm -i path/to/geoipupdate_4.0.0_linux_amd64.rpm` (replacing the +Run `rpm -Uvhi path/to/geoipupdate_4.0.0_linux_amd64.rpm` (replacing the version number and architecture as necessary). You will need to be root. This will install `geoipupdate` to `/usr/bin/geoipupdate`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/cmd/geoipupdate/main.go new/geoipupdate-4.5.0/cmd/geoipupdate/main.go --- old/geoipupdate-4.3.0/cmd/geoipupdate/main.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/cmd/geoipupdate/main.go 2020-10-28 22:03:38.000000000 +0100 @@ -38,7 +38,8 @@ os.Exit(1) } - config, err := geoipupdate.NewConfig(args.ConfigFile, defaultDatabaseDirectory, args.DatabaseDirectory, args.Verbose) + config, err := geoipupdate.NewConfig( + args.ConfigFile, defaultDatabaseDirectory, args.DatabaseDirectory, args.Verbose) if err != nil { fatalLogger(fmt.Sprintf("error loading configuration file %s", args.ConfigFile), err) } @@ -61,15 +62,15 @@ for _, editionID := range config.EditionIDs { filename, err := geoipupdate.GetFilename(config, editionID, client) if err != nil { - return errors.Wrap(err, "error retrieving filename") + return errors.Wrapf(err, "error retrieving filename for %s", editionID) } filePath := filepath.Join(config.DatabaseDirectory, filename) dbWriter, err := database.NewLocalFileDatabaseWriter(filePath, config.LockFile, config.Verbose) if err != nil { - return errors.Wrap(err, "error creating database writer") + return errors.Wrapf(err, "error creating database writer for %s", editionID) } if err := dbReader.Get(dbWriter, editionID); err != nil { - return err + return errors.WithMessagef(err, "error while getting database for %s", editionID) } } return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/conf/GeoIP.conf.default new/geoipupdate-4.5.0/conf/GeoIP.conf.default --- old/geoipupdate-4.3.0/conf/GeoIP.conf.default 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/conf/GeoIP.conf.default 2020-10-28 22:03:38.000000000 +0100 @@ -37,3 +37,10 @@ # Note: Once created, this lockfile is not removed from the filesystem. # Defaults to ".geoipupdate.lock" under the DatabaseDirectory. # LockFile DATADIR/.geoipupdate.lock + +# The amount of time to retry for when errors during HTTP transactions are +# encountered. It can be specified as a (possibly fractional) decimal number +# followed by a unit suffix. Valid time units are "ns", "us" (or "µs"), "ms", +# "s", "m", "h". +# Defaults to "5m" (5 minutes). +# RetryFor 5m diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/doc/GeoIP.conf.md new/geoipupdate-4.5.0/doc/GeoIP.conf.md --- old/geoipupdate-4.3.0/doc/GeoIP.conf.md 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/doc/GeoIP.conf.md 2020-10-28 22:03:38.000000000 +0100 @@ -65,6 +65,13 @@ filesystem. The default is `.geoipupdate.lock` under the `DatabaseDirectory`. +`RetryFor` + +: The amount of time to retry for when errors during HTTP transactions are + encountered. It can be specified as a (possibly fractional) decimal number + followed by a unit suffix. Valid time units are `ns`, `us` (or `µs`), `ms`, + `s`, `m`, `h`. The default is `5m` (5 minutes). + ## Deprecated settings: The following are deprecated and will be ignored if present: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/doc/docker.md new/geoipupdate-4.5.0/doc/docker.md --- old/geoipupdate-4.3.0/doc/docker.md 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/doc/docker.md 2020-10-28 22:03:38.000000000 +0100 @@ -1,5 +1,10 @@ # Docker +## Image information + +The image is available on [Docker Hub](https://hub.docker.com/r/maxmindinc/geoipupdate). +The source code is available on [GitHub](https://github.com/maxmind/geoipupdate). + ## Configuring The Docker image is configured by environment variables. The following @@ -27,7 +32,7 @@ of files downloaded from the server. This option is either `0` or `1`. The default is `0`. * `GEOIPUPDATE_VERBOSE` - Enable verbose mode. Prints out the steps that - `geoipupdate` takes. + `geoipupdate` takes. Set to **anything** (e.g., `1`) to enable. The environment variables can be placed in a file with one per line and passed in with the `--env-file` flag. Alternatively, you may pass them in @@ -35,6 +40,8 @@ ## Running +### docker run + Run the latest image with: ``` @@ -44,3 +51,39 @@ `<file>` should be the environment variable file with your configuration. `<database directory>` should be the local directory that you want to download the databases to. + +### docker-compose + +Run the latest image with: + +``` +version: '3' +services: + geoipupdate: + container_name: geoipupdate + image: maxmindinc/geoipupdate + restart: unless-stopped + environment: + - GEOIPUPDATE_ACCOUNT_ID=XXXXXX + - GEOIPUPDATE_LICENSE_KEY=XXXXXXXXXXXXXXXX + - 'GEOIPUPDATE_EDITION_IDS=GeoLite2-ASN GeoLite2-City GeoLite2-Country' + - GEOIPUPDATE_FREQUENCY=72 + networks: + - geoipupdate + volumes: + - 'geoipupdate_data:/usr/share/GeoIP' + +networks: + geoipupdate: + +volumes: + geoipupdate_data: + driver: local +``` + +Note - When using docker-compose, you need to either: + - set `GEOIPUPDATE_FREQUENCY` equal to something greater than 0 + or + - set `restart: on-failure` + +If you don't, the container will continuously restart. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/docker/entry.sh new/geoipupdate-4.5.0/docker/entry.sh --- old/geoipupdate-4.3.0/docker/entry.sh 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/docker/entry.sh 2020-10-28 22:03:38.000000000 +0100 @@ -39,8 +39,6 @@ flags="-v" fi -cat "$conf_file" - while true; do echo "# STATE: Running geoipupdate" /usr/bin/geoipupdate -d "$database_dir" -f "$conf_file" $flags diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/go.mod new/geoipupdate-4.5.0/go.mod --- old/geoipupdate-4.3.0/go.mod 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/go.mod 2020-10-28 22:03:38.000000000 +0100 @@ -1,14 +1,16 @@ module github.com/maxmind/geoipupdate/v4 -go 1.10 +go 1.11 require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gofrs/flock v0.7.1 - github.com/kr/pretty v0.2.0 // indirect + github.com/gofrs/flock v0.8.0 + github.com/kr/text v0.2.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.5.1 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.7 // indirect + github.com/stretchr/testify v1.6.1 + golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1 // indirect + gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/go.sum new/geoipupdate-4.5.0/go.sum --- old/geoipupdate-4.3.0/go.sum 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/go.sum 2020-10-28 22:03:38.000000000 +0100 @@ -1,16 +1,16 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= -github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/maxmind/geoipupdate v4.0.2+incompatible h1:G1tXaGXl3kfFUYE9/pyico4J6OKWFL79i0XVUdbMebk= -github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k= -github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -19,16 +19,14 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.0 h1:DMOzIV76tmoDNE9pX6RSN0aDtCYeCg5VueieJaAo1uw= -github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1 h1:/DtoiOYKoQCcIFXQjz07RnWNPRCbqmSXSpgEzhC9ZHM= +golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +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= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/config.go new/geoipupdate-4.5.0/pkg/geoipupdate/config.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/config.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/config.go 2020-10-28 22:03:38.000000000 +0100 @@ -9,6 +9,7 @@ "regexp" "strconv" "strings" + "time" "github.com/pkg/errors" ) @@ -24,6 +25,7 @@ Proxy *url.URL PreserveFileTimes bool Verbose bool + RetryFor time.Duration } // NewConfig parses the configuration file. @@ -101,6 +103,12 @@ proxyUserPassword = value case "Protocol", "SkipHostnameVerification", "SkipPeerVerification": // Deprecated. + case "RetryFor": + dur, err := time.ParseDuration(value) + if err != nil || dur < 0 { + return nil, errors.Errorf("'%s' is not a valid duration", value) + } + config.RetryFor = dur default: return nil, errors.Errorf("unknown option on line %d", lineNumber) } @@ -124,6 +132,10 @@ // Set defaults & post-process. + if _, ok := keysSeen["RetryFor"]; !ok { + config.RetryFor = 5 * time.Minute + } + // Argument takes precedence. if databaseDirectory != "" { config.DatabaseDirectory = filepath.Clean(databaseDirectory) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/config_test.go new/geoipupdate-4.5.0/pkg/geoipupdate/config_test.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/config_test.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/config_test.go 2020-10-28 22:03:38.000000000 +0100 @@ -7,6 +7,7 @@ "os" "path/filepath" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -60,6 +61,13 @@ # Note: Once created, this lockfile is not removed from the filesystem. # Defaults to ".geoipupdate.lock" under the DatabaseDirectory. # LockFile DATADIR/.geoipupdate.lock + +# The amount of time to retry for when errors during HTTP transactions are +# encountered. It can be specified as a (possibly fractional) decimal number +# followed by a unit suffix. Valid time units are "ns", "us" (or "µs"), "ms", +# "s", "m", "h". +# Defaults to "5m" (5 minutes). +# RetryFor 5m `, Output: &Config{ AccountID: 42, @@ -68,6 +76,7 @@ EditionIDs: []string{"GeoLite2-Country", "GeoLite2-City"}, LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { @@ -119,6 +128,7 @@ EditionIDs: []string{"GeoLite2-Country", "GeoLite2-City"}, LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { @@ -162,6 +172,8 @@ # Note: Once created, this lockfile is not removed from the filesystem. # Defaults to ".geoipupdate.lock" under the DatabaseDirectory. LockFile /usr/lock + +RetryFor 10m `, Output: &Config{ AccountID: 1234, @@ -176,6 +188,7 @@ }, PreserveFileTimes: true, URL: "https://updates.example.com", + RetryFor: 10 * time.Minute, }, }, { @@ -252,6 +265,20 @@ Err: "geoipupdate requires a valid AccountID and LicenseKey combination", }, { + Description: "RetryFor needs a unit", + Input: `AccountID 42 +LicenseKey 000000000001 +RetryFor 5`, + Err: "'5' is not a valid duration", + }, + { + Description: "RetryFor needs to be non-negative", + Input: `AccountID 42 +LicenseKey 000000000001 +RetryFor -5m`, + Err: "'-5m' is not a valid duration", + }, + { Description: "AccountID 999999 with a non-000000000000 LicenseKey is treated normally", Input: `AccountID 999999 LicenseKey abcd @@ -263,6 +290,7 @@ LicenseKey: "abcd", LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { @@ -281,6 +309,7 @@ LicenseKey: "abcd", LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { @@ -293,12 +322,14 @@ LicenseKey: "123", LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { Description: "CR line ending does not work", Input: "AccountID 0\rLicenseKey 123\rEditionIDs GeoIP2-City\r", - Err: `invalid account ID format: strconv.Atoi: parsing "0 LicenseKey 123 EditionIDs GeoIP2-City": invalid syntax`, + // nolint: lll + Err: `invalid account ID format: strconv.Atoi: parsing "0 LicenseKey 123 EditionIDs GeoIP2-City": invalid syntax`, }, { Description: "Multiple spaces between option and value works", @@ -313,11 +344,13 @@ LicenseKey: "456", LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, { Description: "Tabs between options and values works", - Input: "AccountID\t123\nLicenseKey\t\t456\nEditionIDs\t\t\tGeoLite2-City\t\t\t\tGeoLite2-Country\t\t\t\t\n", + + Input: "AccountID\t123\nLicenseKey\t\t456\nEditionIDs\t\t\tGeoLite2-City\t\t\t\tGeoLite2-Country\t\t\t\t\n", Output: &Config{ AccountID: 123, DatabaseDirectory: filepath.Clean("/tmp"), @@ -325,6 +358,7 @@ LicenseKey: "456", LockFile: filepath.Clean("/tmp/.geoipupdate.lock"), URL: "https://updates.maxmind.com", + RetryFor: 5 * time.Minute, }, }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/database/http_reader.go new/geoipupdate-4.5.0/pkg/geoipupdate/database/http_reader.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/database/http_reader.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/database/http_reader.go 2020-10-28 22:03:38.000000000 +0100 @@ -1,3 +1,5 @@ +// Package database provides an abstraction over getting and writing a +// database file. package database import ( @@ -11,6 +13,7 @@ "time" "github.com/maxmind/geoipupdate/v4/pkg/geoipupdate" + "github.com/maxmind/geoipupdate/v4/pkg/geoipupdate/internal" "github.com/pkg/errors" ) @@ -18,6 +21,7 @@ // databases. type HTTPDatabaseReader struct { client *http.Client + retryFor time.Duration url string licenseKey string accountID int @@ -30,6 +34,7 @@ func NewHTTPDatabaseReader(client *http.Client, config *geoipupdate.Config) Reader { return &HTTPDatabaseReader{ client: client, + retryFor: config.RetryFor, url: config.URL, licenseKey: config.LicenseKey, accountID: config.AccountID, @@ -54,7 +59,7 @@ url.QueryEscape(destination.GetHash()), ) - req, err := http.NewRequest(http.MethodGet, maxMindURL, nil) + req, err := http.NewRequest(http.MethodGet, maxMindURL, nil) // nolint: noctx if err != nil { return errors.Wrap(err, "error creating request") } @@ -63,7 +68,7 @@ if reader.verbose { log.Printf("Performing update request to %s", maxMindURL) } - response, err := reader.client.Do(req) + response, err := internal.MaybeRetryRequest(reader.client, reader.retryFor, req) if err != nil { return errors.Wrap(err, "error performing HTTP request") } @@ -98,7 +103,7 @@ } }() - if _, err = io.Copy(destination, gzReader); err != nil { + if _, err = io.Copy(destination, gzReader); err != nil { //nolint:gosec return errors.Wrap(err, "error writing response") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/database/http_reader_test.go new/geoipupdate-4.5.0/pkg/geoipupdate/database/http_reader_test.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/database/http_reader_test.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/database/http_reader_test.go 2020-10-28 22:03:38.000000000 +0100 @@ -97,6 +97,7 @@ DownloadHeaders: map[string]string{ "X-Database-MD5": "5d41402abc4b2a76b9719d911017c592", // "hello" }, + // nolint: lll Err: `md5 of new database \(985ecf3d7959b146208b3dc0189b21a5\) does not match expected md5 \(5d41402abc4b2a76b9719d911017c592\)`, }, { @@ -203,7 +204,7 @@ err := ioutil.WriteFile( currentDatabasePath, []byte(test.DatabaseBefore), - 0644, + 0600, ) require.NoError(t, err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/database/local_file_writer.go new/geoipupdate-4.5.0/pkg/geoipupdate/database/local_file_writer.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/database/local_file_writer.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/database/local_file_writer.go 2020-10-28 22:03:38.000000000 +0100 @@ -31,7 +31,7 @@ // NewLocalFileDatabaseWriter create a LocalFileDatabaseWriter. It creates the // necessary lock and temporary files to protect the database from concurrent // writes. -func NewLocalFileDatabaseWriter(filePath string, lockFilePath string, verbose bool) (*LocalFileDatabaseWriter, error) { +func NewLocalFileDatabaseWriter(filePath, lockFilePath string, verbose bool) (*LocalFileDatabaseWriter, error) { dbWriter := &LocalFileDatabaseWriter{ filePath: filePath, lockFilePath: lockFilePath, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/database/writer.go new/geoipupdate-4.5.0/pkg/geoipupdate/database/writer.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/database/writer.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/database/writer.go 2020-10-28 22:03:38.000000000 +0100 @@ -1,13 +1,14 @@ package database import ( - "github.com/gofrs/flock" - "github.com/pkg/errors" "io" "log" "os" "path/filepath" "time" + + "github.com/gofrs/flock" + "github.com/pkg/errors" ) // ZeroMD5 is the default value provided as an MD5 hash for a non-existent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/database/writer_test.go new/geoipupdate-4.5.0/pkg/geoipupdate/database/writer_test.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/database/writer_test.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/database/writer_test.go 2020-10-28 22:03:38.000000000 +0100 @@ -1,12 +1,13 @@ package database import ( - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "io/ioutil" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCreateLockFile(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/geoip_updater.go new/geoipupdate-4.5.0/pkg/geoipupdate/geoip_updater.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/geoip_updater.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/geoip_updater.go 2020-10-28 22:03:38.000000000 +0100 @@ -1,3 +1,5 @@ +// Package geoipupdate provides a library for using MaxMind's GeoIP Update +// service. package geoipupdate import ( @@ -9,6 +11,7 @@ "net/http" "net/url" + "github.com/maxmind/geoipupdate/v4/pkg/geoipupdate/internal" "github.com/pkg/errors" ) @@ -16,14 +19,12 @@ func NewClient( config *Config, ) *http.Client { - var client *http.Client transport := http.DefaultTransport if config.Proxy != nil { proxy := http.ProxyURL(config.Proxy) transport.(*http.Transport).Proxy = proxy } - client = &http.Client{Transport: transport} - return client + return &http.Client{Transport: transport} } // GetFilename looks up the filename for the given edition ID. @@ -41,7 +42,11 @@ if config.Verbose { log.Printf("Performing get filename request to %s", maxMindURL) } - res, err := client.Get(maxMindURL) + req, err := http.NewRequest(http.MethodGet, maxMindURL, nil) // nolint: noctx + if err != nil { + return "", errors.Wrap(err, "error creating HTTP request") + } + res, err := internal.MaybeRetryRequest(client, config.RetryFor, req) if err != nil { return "", errors.Wrap(err, "error performing HTTP request") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/geoip_updater_test.go new/geoipupdate-4.5.0/pkg/geoipupdate/geoip_updater_test.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/geoip_updater_test.go 2020-04-16 18:35:28.000000000 +0200 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/geoip_updater_test.go 2020-10-28 22:03:38.000000000 +0100 @@ -1,14 +1,15 @@ package geoipupdate import ( - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "io/ioutil" "net/http" "net/http/httptest" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetFileName(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/internal/retry.go new/geoipupdate-4.5.0/pkg/geoipupdate/internal/retry.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/internal/retry.go 1970-01-01 01:00:00.000000000 +0100 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/internal/retry.go 2020-10-28 22:03:38.000000000 +0100 @@ -0,0 +1,47 @@ +// Package internal is none of your business +package internal + +import ( + "net/http" + "time" + + "github.com/pkg/errors" +) + +// MaybeRetryRequest is an internal implementation detail of this module. It +// shouldn't be used by users of the geoipupdate Go library. You can use the +// RetryFor field of geoipupdate.Config if you'd like to retry failed requests +// when using the library directly. +func MaybeRetryRequest(c *http.Client, retryFor time.Duration, req *http.Request) (*http.Response, error) { + if retryFor < 0 { + return nil, errors.New("negative retry duration") + } + if req.Body != nil { + return nil, errors.New("can't retry requests with bodies") + } + var resp *http.Response + var err error + + start := time.Now() + for i := uint(0); ; i++ { + resp, err = c.Do(req) + if err == nil && resp.StatusCode < 500 { + break + } + + currentDuration := time.Since(start) + + waitDuration := 200 * time.Millisecond * (1 << i) + if currentDuration+waitDuration > retryFor { + break + } + if err == nil { + _ = resp.Body.Close() + } + time.Sleep(waitDuration) + } + if err != nil { + return nil, errors.Wrap(err, "error performing http request") + } + return resp, nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geoipupdate-4.3.0/pkg/geoipupdate/internal/retry_test.go new/geoipupdate-4.5.0/pkg/geoipupdate/internal/retry_test.go --- old/geoipupdate-4.3.0/pkg/geoipupdate/internal/retry_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/geoipupdate-4.5.0/pkg/geoipupdate/internal/retry_test.go 2020-10-28 22:03:38.000000000 +0100 @@ -0,0 +1,71 @@ +package internal + +import ( + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRetry(t *testing.T) { + { + n, resp, err := testRetry( // nolint: bodyclose + t, + func(n int, causeError func()) int { + causeError() + return http.StatusOK + }, + ) + assert.Equal(t, 5, n) + assert.Error(t, err) + assert.Nil(t, resp) + } + + { + n, resp, err := testRetry( + t, + func(n int, causeError func()) int { + if n < 3 { + causeError() + } + return http.StatusOK + }, + ) + assert.Equal(t, 3, n) + assert.NoError(t, err) + assert.NotNil(t, resp) + require.NoError(t, resp.Body.Close()) + } + + { + n, resp, err := testRetry( + t, + func(int, func()) int { return http.StatusInternalServerError }, + ) + assert.Equal(t, 5, n) + assert.NoError(t, err) + require.NoError(t, resp.Body.Close()) + } +} + +func testRetry(t *testing.T, cb func(int, func()) int) (int, *http.Response, error) { + var server *httptest.Server + requests := 0 + server = httptest.NewServer( + http.HandlerFunc( + func(rw http.ResponseWriter, r *http.Request) { + requests++ + rw.WriteHeader(cb(requests, func() { server.CloseClientConnections() })) + }, + ), + ) + + req, err := http.NewRequest(http.MethodGet, server.URL, nil) // nolint: noctx + require.NoError(t, err) + resp, err := MaybeRetryRequest(server.Client(), 6*time.Second, req) + server.Close() + return requests, resp, err +} ++++++ vendor.tar.gz ++++++ ++++ 179273 lines of diff (skipped)