Currently Athens only supports connecting to Redis using a hostname:port combination in addition to a password. While this works in most cases it also means that if you have other options you wish to supply Athens has to be updated to support them. As a basic example Redis clusters that require TLS currently are not supported by Athens but with this change you can simply supply a [redis url](https://github.com/redis/redis-specifications/blob/master/uri/redis.txt) to connect over TLS. It also makes it easy to override the password, set a username and more all from a single configuration option:
`rediss://username:password@redis.example.com:6379/1?protocol=3`
Upgrades to the Go 1.22 toolchain. Upgrades golangci-lint to 1.61.0 and disables some new linters.
---------
Co-authored-by: Nicholas Wiersma <nick@wiersma.co.za>
Uses the new Azure Identity package for current support. Support automated Azure storage token refresh. Sets the default value of Athens storage account key and Azure managed identity resource id should be empty.
Set correct Content-Type headers on each endpoint rather than on the router. The router would, at times, send two Content-Type headers and other times just send the wrong one.
* gcp/saver: Only return errors.KindAlreadyExists if all three exist
In #1124, a GCP lock type was added as a singleflight backend. As part of this work, the GCP backend's Save() was made serial, likely because moduploader.Upload requires a call to Exists() before it, rendering the GCP lock less useful, by doubling the calls to GCS.
However, by doing this, the existence check was now only checking the existence of the mod file, and not the info or zip. This meant that if during a Save, the zip or info uploads failed, on subsequent rquests, that when using the GCP singleflight backend, Athens would assume everything had been stashed and saved properly, and then fail to serve up the info or zip that had failed upload, meaning the cache was in an unhealable broklen state, requiring a manual intervention.
To fix this, without breaking the singleflight behavior, introduce a metadata key that is set on the mod file during its initial upload, indicating that a Stash is still in progress on subsequent files, which gets removed once all three files are uploaded successfully, which can be checked if it it is determined that the mod file already exists. That way we can return a errors.KindAlreadyExists if a Stash is in progress, but also properly return it when a Stash is *not* currently in progress if and only if all three files exist on GCS, which prevents the cache from becoming permanently poisoned.
One note is that it is possible the GCS call to remove the metadata key fails, which would mean it is left on the mod object forever. To avoid this, consider it stale after 2 minutes.
---------
Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
Co-authored-by: Matt <matt.ouille@protonmail.com>
A default homepage is baked into the server that uses the request host address, or in HTTP 2 the authority. This includes ports. It also checks for schema. The values are used to indicate to users how to configure their go env
Of course, this won't work on all installations - especially enterprise ones. For that, we've introduced ATHENS_HOME_TEMPLATE_PATH as an environment variable along with HomeTemplatePath in the config. This value defaults to /var/lib/athens/home.html but can be configured to any location that Athens can reliably read from. This is a Go HTML template so it should use Go HTML template formatting and logic.
Fix an issue in the Stasher where contexts between the request and log entry are not copied correctly.
Co-authored-by: ouyangxu <ouyangxu@bilibili.com>
Adds a log format setting as ATHENS_LOG_FORMAT that can be either plain or JSON when CloudRuntime is none (the default). Does not break or change any existing behavior.
* Using HeadObject to check the existence of a module
* fixing build
* calling cancel before closing channel
* fixing test
* using waitgroup
* calling cancel
* calling wg.Done
* only return the first error
* Revert "only return the first error"
This reverts commit c0aa18b522.
* clean err if not exist
S3 API sometimes returns duplicate keys, causing the number of file for a specific module greater than 3. This PR makes Athens handle that situation gracefully and log a warning message instead of treating the module as not found.
logging string content
Co-authored-by: Manu Gupta <manugupt1@gmail.com>
Co-authored-by: Ashish Ranjan <ashishranjan2912@gmail.com>
This commit replaces `os.Setenv` with `t.Setenv` in tests. The
environment variable is automatically restored to its original value
when the test and all its subtests complete.
Reference: https://pkg.go.dev/testing#T.Setenv
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
Co-authored-by: Ashish Ranjan <ashishranjan2912@gmail.com>
Currently, when shutting down the server (via SIGINT or SIGTERM), the
shutdown closes any open connections after only 10 seconds (via a
context.WithTimeout). This does not provie a lot of time for longer
operations, such as listing versions, or downloading a larger module zip
file.
When running in Kubernetes, and scaling instances or changing config,
this causes a lot of dropped connections and gateway errors. 10 seconds
is arguably much too short, and should be configurable.
This commit increases that default to 60 seconds, and adds a config
variable to allow users to specify their desired timeout.
* read redis lock options from config to support custom TTL & timeout
* fix test
* fix typo
* downgrade to bsm/redislock@v0.7.2 to prevent usage of beta go-redis version
* revert test changes
* return error for invalid lock config
* update config parsing test
* udpate docs to include redis lock config
* fix test
* set default max retries to 10
* reduce default redis lock timeout to 15s
* update default TTL to 15mins
Co-authored-by: Manu Gupta <manugupt1@gmail.com>
When using Minio storage, memory usage constantly increases. After
profiling, it appears that memory usage is building in the minio client,
and not being released.
Finding a similar issue listed in the minio/warp project, I found that
they fixed the issue by closing the *minio.Object instances. In the
athens usage, the minio.Object instances are never closed after reading
the data from them.
This adds deferred 'Close' calls in the 'storageImpl.Info' and
'storageImpl.GoMod' functions so that the objects may be released and
garbage collected. The 'storageImpl.Zip' function does not use defer,
since it has the object embedded into the return value, so the 'Close'
is only called on error.
* fix: flake on redis-sentinel by depending on redis container / step.
Signed-off-by: Manu Gupta <manugupt1@gmail.com>
* Add retries in an attempt to reduce the number of flakes
Also; update go-redis.
Co-authored-by: Aaron Schlesinger <70865+arschles@users.noreply.github.com>
* Set GO111MODULE to auto in golint script– #1743
As mentioned in #1743 the Go modules environment flag is set to `off`
in the script which appears to cause a warning message for each module
of the codebase that it is "not in GOROOT".
Set to `auto` as this allows the same build to be run the original way
should someone choose to delete the `go.mod` file from the project root.
* Remove redundant code – golint script
Go 1.17 ignores `GO111MODULE` and there are no directories in the
project root called `mock`.
* Replace `golint` with `go vet`
`golint` is deprecated (and frozen) replace with the current `go vet`.
This reported one issue on `main` branch:
```pkg/stash/with_etcd.go:33:28:
loop variable ep captured by func literal```
Fixed loop variable capture with extraction to parameterised anonymous
function passed loop variable and passed in to `errgroup.Go` call.