Compare commits

...

36 Commits

Author SHA1 Message Date
Harshavardhana 62383dfbfe
Fix formatting of features in README.md
VulnCheck / Analysis (push) Waiting to run Details
2025-10-07 09:59:23 -07:00
Ravind Kumar bde0d5a291
Updating readme for MinIO docs (#21625)
VulnCheck / Analysis (push) Waiting to run Details
2025-10-06 22:36:26 -07:00
yangw 534f4a9fb1
fix: timeN function return final closure not be called (#21615)
VulnCheck / Analysis (push) Has been cancelled Details
2025-09-30 23:06:01 -07:00
Klaus Post b8631cf531
Use new gofumpt (#21613)
VulnCheck / Analysis (push) Has been cancelled Details
Update tinylib. Should fix CI.

`gofumpt -w .&&go generate ./...`
2025-09-28 13:59:21 -07:00
jiuker 456d9462e5
fix: after saveRebalanceStats cancel will be empty (#21597) 2025-09-19 21:51:57 -07:00
jiuker 756f3c8142
fix: incorrect poolID when after decommission adding pools (#21590) 2025-09-18 04:47:48 -07:00
mosesdd 7a80ec1cce
fix: LDAP TLS handshake fails with StartTLS and tls_skip_verify=off (#21582)
Fixes #21581
2025-09-17 00:58:27 -07:00
M Alvee ae71d76901
fix: remove unnecessary replication checks (#21569) 2025-09-08 10:43:13 -07:00
M Alvee 07c3a429bf
fix: conditional checks write for multipart (#21567) 2025-09-07 09:13:09 -07:00
Minio Trusted 0cde982902 Update yaml files to latest version RELEASE.2025-09-06T17-38-46Z 2025-09-07 05:14:10 +00:00
Ian Roberts d0f50cdd9b
fix: use correct dummy ARN for claim-based OIDC provider when listing access keys (#21549)
fix: use correct dummy ARN for claim-based OIDC provider

When listing OIDC access keys, use the correct ARN when looking up the provider configuration for the claim-based provider.  Without this it was impossible to list access keys for a claim-based provider, only for a role-policy-based provider.

Fixes minio/minio#21548
2025-09-06 10:38:46 -07:00
WGH da532ab93d
Fix support for legacy compression env variables (#21533)
Commit b6eb8dff64 renamed compression
setting environment variables to follow consistent style.

Although it preserved backward compatibility for the most part (i.e. it
handled MINIO_COMPRESS_ALLOW_ENCRYPTION, MINIO_COMPRESS_EXTENSIONS, and
MINIO_COMPRESS_MIME_TYPES), MINIO_COMPRESS_ENABLE was left behind.

Additionally, due to incorrect fallback ordering, and DefaultKVS
containing enable=off allow_encryption=off (so kvs.Get should've been
tried last), that commit broke MINIO_COMPRESS_ALLOW_ENCRYPTION (even
though it appeared to be handled), and even older MINIO_COMPRESS, too.

The legacy MIME types and extensions variables take precedence over both
config and new variables, so they don't need fixing.
2025-09-06 10:37:10 -07:00
M Alvee 558fc1c09c
fix: return error on conditional write for non existing object (#21550) 2025-09-06 10:34:38 -07:00
Alex 9fdbf6fe83
Updated object-browser to the latest version v2.0.4 (#21564)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2025-09-06 10:33:19 -07:00
jiuker 5c87d4ae87
fix: when save the rebalanceStats not found the config file (#21547) 2025-09-04 13:47:24 -07:00
Klaus Post f0b91e5504
Run modernize (#21546)
`go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...` executed.

`go generate ./...` ran afterwards to keep generated.
2025-08-28 19:39:48 -07:00
Manuel Reis 3b7cb6512c
Revert `dns.msgUnPath`, fixes #21541 (#21542)
* Add more tests to UnPath function
* Revert implementation on dns.msgUnPath. Fixes: #21541
2025-08-28 10:31:12 -07:00
Mark Theunissen 4ea6f3b06b
fix: invalid checksum on site replication with conforming checksum types (#21535) 2025-08-22 07:15:21 -07:00
jiuker 86d9d9b55e
fix: use amqp.ParseURL to parse amqp url (#21528) 2025-08-20 21:25:07 -07:00
Denis Peshkov 5a35585acd
http/listener: fix bugs and simplify (#21514)
* Store `ctx.Done` channel in a struct instead of a `ctx`. See: https://go.dev/blog/context-and-structs
* Return from `handleListener` on `ctx` cancellation, preventing goroutine leaks
* Simplify `handleListener` by removing the `send` closure. The `handleListener` is inlined by the compiler
* Return the first error from `Close`
* Preallocate slice in `Addrs`
* Reduce duplication in handling `opts.Trace`
* http/listener: revert error propagation from Close()
* http/listener: preserve original listener address in Addr()
* Preserve the original address when calling Addr() with multiple listeners
* Remove unused listeners from the slice
2025-08-12 11:22:12 -07:00
Daryl White 0848e69602
Update docs links throughout (#21513) 2025-08-12 11:20:36 -07:00
M Alvee 02ba581ecf
custom user-agent transport wrapper (#21483) 2025-08-08 10:51:53 -07:00
Ian Roberts b44b2a090c
fix: when claim-based OIDC is configured, treat unknown roleArn as claim-based auth (#21512)
RoleARN is a required parameter in AssumeRoleWithWebIdentity, 
according to the standard AWS implementation, and the official 
AWS SDKs and CLI will not allow you to assume a role from a JWT 
without also specifying a RoleARN.  This meant that it was not 
possible to use the official SDKs for claim-based OIDC with Minio 
(minio/minio#21421), since Minio required you to _omit_ the RoleARN in this case.

minio/minio#21468 attempted to fix this by disabling the validation 
of the RoleARN when a claim-based provider was configured, but this had 
the side effect of making it impossible to have a mixture of claim-based 
and role-based OIDC providers configured at the same time - every 
authentication would be treated as claim-based, ignoring the RoleARN entirely.

This is an alternative fix, whereby:

- _if_ the `RoleARN` is one that Minio knows about, then use the associated role policy
- if the `RoleARN` is not recognised, but there is a claim-based provider configured, then ignore the role ARN and attempt authentication with the claim-based provider
- if the `RoleARN` is not recognised, and there is _no_ claim-based provider, then return an error.
2025-08-08 10:51:23 -07:00
dorman c7d6a9722d
Modify permission verification type (#21505) 2025-08-08 02:47:37 -07:00
jiuker a8abdc797e
fix: add name and description to ldap accesskey list (#21511) 2025-08-07 19:46:04 -07:00
M Alvee 0638ccc5f3
fix: claim based oidc for official aws libraries (#21468) 2025-08-07 19:42:38 -07:00
jiuker b1a34fd63f
fix: errUploadIDNotFound will be ignored when err is from peer client (#21504) 2025-08-07 19:38:41 -07:00
Klaus Post ffcfa36b13
Check legalHoldPerm (#21508)
The provided parameter should be checked before accepting legal hold
2025-08-07 19:38:25 -07:00
Aditya Kotra 376fbd11a7
fix(helm): do not suspend versioning by default for buckets, only set versioning if specified(21349) (#21494)
Signed-off-by: Aditya Kotra <kaditya030@gmail.com>
2025-08-07 02:47:02 -07:00
dorman c76f209ccc
Optimize outdated commands in the log (#21498) 2025-08-06 16:48:58 -07:00
M Alvee 7a6a2256b1
imagePullSecrets consistent types for global , local (#21500) 2025-08-06 16:48:24 -07:00
Johannes Horn d002beaee3
feat: add variable for datasource in grafana dashboards (#21470) 2025-08-03 18:46:49 -07:00
jiuker 71f293d9ab
fix: record extral skippedEntry for listObject (#21484)
VulnCheck / Analysis (push) Has been cancelled Details
Lock Threads / action (push) Has been cancelled Details
2025-08-01 08:53:35 -07:00
jiuker e3d183b6a4
bring more idempotent behavior to AbortMultipartUpload() (#21475)
VulnCheck / Analysis (push) Has been cancelled Details
fix #21456
2025-07-30 23:57:23 -07:00
Alex 752abc2e2c
Update console to v2.0.3 (#21474)
VulnCheck / Analysis (push) Waiting to run Details
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2025-07-30 10:57:17 -07:00
Minio Trusted b9f0e8c712 Update yaml files to latest version RELEASE.2025-07-23T15-54-02Z
VulnCheck / Analysis (push) Has been cancelled Details
2025-07-23 18:28:46 +00:00
436 changed files with 2490 additions and 2787 deletions

283
README.md
View File

@ -4,268 +4,109 @@
[![MinIO](https://raw.githubusercontent.com/minio/minio/master/.github/logo.svg?sanitize=true)](https://min.io)
MinIO is a high-performance, S3-compatible object storage solution released under the GNU AGPL v3.0 license. Designed for speed and scalability, it powers AI/ML, analytics, and data-intensive workloads with industry-leading performance.
MinIO is a high-performance, S3-compatible object storage solution released under the GNU AGPL v3.0 license.
Designed for speed and scalability, it powers AI/ML, analytics, and data-intensive workloads with industry-leading performance.
🔹 S3 API Compatible Seamless integration with existing S3 tools
🔹 Built for AI & Analytics Optimized for large-scale data pipelines
🔹 High Performance Ideal for demanding storage workloads.
- S3 API Compatible Seamless integration with existing S3 tools
- Built for AI & Analytics Optimized for large-scale data pipelines
- High Performance Ideal for demanding storage workloads.
AI storage documentation (https://min.io/solutions/object-storage-for-ai).
This README provides instructions for building MinIO from source and deploying onto baremetal hardware.
For more complete documentation, see [the MinIO documentation website](https://docs.min.io/community/minio-object-store/index.html)
This README provides quickstart instructions on running MinIO on bare metal hardware, including container-based installations. For Kubernetes environments, use the [MinIO Kubernetes Operator](https://github.com/minio/operator/blob/master/README.md).
## MinIO is Open Source Software
## Container Installation
We designed MinIO as Open Source software for the Open Source software community.
We encourage the community to remix, redesign, and reshare MinIO under the terms of the AGPLv3 license.
Use the following commands to run a standalone MinIO server as a container.
All usage of MinIO in your application stack requires validation against AGPLv3 obligations, which include but are not limited to the release of modified code to the community from which you have benefited.
Any commercial/proprietary usage of the AGPLv3 software, including repackaging or reselling services/features, is done at your own risk.
Standalone MinIO servers are best suited for early development and evaluation. Certain features such as versioning, object locking, and bucket replication
require distributed deploying MinIO with Erasure Coding. For extended development and production, deploy MinIO with Erasure Coding enabled - specifically,
with a *minimum* of 4 drives per MinIO server. See [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html)
for more complete documentation.
The AGPLv3 provides no obligation by any party to support, maintain, or warranty the original or any modified work.
All support is provided on a best-effort basis through Github and our [Slack](https//slack.min.io) channel, and any member of the community is welcome to contribute and assist others in their usage of the software.
### Stable
MinIO [AIStor](https://www.min.io/product/aistor) includes enterprise-grade support and licensing for workloads which require commercial or proprietary usage and production-level SLA/SLO-backed support.
For more information, [reach out for a quote](https://min.io/pricing).
Run the following command to run the latest stable image of MinIO as a container using an ephemeral data volume:
## Legacy Releases
```sh
podman run -p 9000:9000 -p 9001:9001 \
quay.io/minio/minio server /data --console-address ":9001"
```
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded
object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the
root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See
[Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers,
see <https://min.io/docs/minio/linux/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
> [!NOTE]
> To deploy MinIO on with persistent storage, you must map local persistent directories from the host OS to the container using the `podman -v` option.
> For example, `-v /mnt/data:/data` maps the host OS drive at `/mnt/data` to `/data` on the container.
## macOS
Use the following commands to run a standalone MinIO server on macOS.
Standalone MinIO servers are best suited for early development and evaluation. Certain features such as versioning, object locking, and bucket replication require distributed deploying MinIO with Erasure Coding. For extended development and production, deploy MinIO with Erasure Coding enabled - specifically, with a *minimum* of 4 drives per MinIO server. See [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html) for more complete documentation.
### Homebrew (recommended)
Run the following command to install the latest stable MinIO package using [Homebrew](https://brew.sh/). Replace ``/data`` with the path to the drive or directory in which you want MinIO to store data.
```sh
brew install minio/stable/minio
minio server /data
```
> [!NOTE]
> If you previously installed minio using `brew install minio` then it is recommended that you reinstall minio from `minio/stable/minio` official repo instead.
```sh
brew uninstall minio
brew install minio/stable/minio
```
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers, see <https://min.io/docs/minio/linux/developers/minio-drivers.html/> to view MinIO SDKs for supported languages.
### Binary Download
Use the following command to download and run a standalone MinIO server on macOS. Replace ``/data`` with the path to the drive or directory in which you want MinIO to store data.
```sh
wget https://dl.min.io/server/minio/release/darwin-amd64/minio
chmod +x minio
./minio server /data
```
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers, see <https://min.io/docs/minio/linux/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
## GNU/Linux
Use the following command to run a standalone MinIO server on Linux hosts running 64-bit Intel/AMD architectures. Replace ``/data`` with the path to the drive or directory in which you want MinIO to store data.
```sh
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
./minio server /data
```
The following table lists supported architectures. Replace the `wget` URL with the architecture for your Linux host.
| Architecture | URL |
| -------- | ------ |
| 64-bit Intel/AMD | <https://dl.min.io/server/minio/release/linux-amd64/minio> |
| 64-bit ARM | <https://dl.min.io/server/minio/release/linux-arm64/minio> |
| 64-bit PowerPC LE (ppc64le) | <https://dl.min.io/server/minio/release/linux-ppc64le/minio> |
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers, see <https://min.io/docs/minio/linux/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
> [!NOTE]
> Standalone MinIO servers are best suited for early development and evaluation. Certain features such as versioning, object locking, and bucket replication require distributed deploying MinIO with Erasure Coding. For extended development and production, deploy MinIO with Erasure Coding enabled - specifically, with a *minimum* of 4 drives per MinIO server. See [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html#) for more complete documentation.
## Microsoft Windows
To run MinIO on 64-bit Windows hosts, download the MinIO executable from the following URL:
```sh
https://dl.min.io/server/minio/release/windows-amd64/minio.exe
```
Use the following command to run a standalone MinIO server on the Windows host. Replace ``D:\`` with the path to the drive or directory in which you want MinIO to store data. You must change the terminal or powershell directory to the location of the ``minio.exe`` executable, *or* add the path to that directory to the system ``$PATH``:
```sh
minio.exe server D:\
```
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers, see <https://min.io/docs/minio/linux/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
> [!NOTE]
> Standalone MinIO servers are best suited for early development and evaluation. Certain features such as versioning, object locking, and bucket replication require distributed deploying MinIO with Erasure Coding. For extended development and production, deploy MinIO with Erasure Coding enabled - specifically, with a *minimum* of 4 drives per MinIO server. See [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html#) for more complete documentation.
MinIO has no planned or scheduled releases for this repository.
While a new release may be cut at any time, there is no timeline for when a subsequent release may occur.
All existing releases remain accessible through Github or at https://dl.min.io/server/minio/release/ .
## Install from Source
Use the following commands to compile and run a standalone MinIO server from source. Source installation is only intended for developers and advanced users. If you do not have a working Golang environment, please follow [How to install Golang](https://golang.org/doc/install). Minimum version required is [go1.24](https://golang.org/dl/#stable)
Use the following commands to compile and run a standalone MinIO server from source.
If you do not have a working Golang environment, please follow [How to install Golang](https://golang.org/doc/install). Minimum version required is [go1.24](https://golang.org/dl/#stable)
```sh
go install github.com/minio/minio@latest
```
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`. You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server. Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials. You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can alternatively run `go build` and use the `GOOS` and `GOARCH` environment variables to control the OS and architecture target.
For example:
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool. See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool. For application developers, see <https://min.io/docs/minio/linux/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
```
env GOOS=linux GOARCh=arm64 go build
```
Start MinIO by running `minio server PATH` where `PATH` is any empty folder on your local filesystem.
The MinIO deployment starts using default root credentials `minioadmin:minioadmin`.
You can test the deployment using the MinIO Console, an embedded web-based object browser built into MinIO Server.
Point a web browser running on the host machine to <http://127.0.0.1:9000> and log in with the root credentials.
You can use the Browser to create buckets, upload objects, and browse the contents of the MinIO server.
You can also connect using any S3-compatible tool, such as the MinIO Client `mc` commandline tool:
```sh
mc alias set local http://localhost:9000 minioadmin minioadmin
mc admin info local
```
See [Test using MinIO Client `mc`](#test-using-minio-client-mc) for more information on using the `mc` commandline tool.
For application developers, see <https://docs.min.io/community/minio-object-store/developers/minio-drivers.html> to view MinIO SDKs for supported languages.
> [!NOTE]
> Standalone MinIO servers are best suited for early development and evaluation. Certain features such as versioning, object locking, and bucket replication require distributed deploying MinIO with Erasure Coding. For extended development and production, deploy MinIO with Erasure Coding enabled - specifically, with a *minimum* of 4 drives per MinIO server. See [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html) for more complete documentation.
MinIO strongly recommends *against* using compiled-from-source MinIO servers for production environments.
## Deployment Recommendations
### Allow port access for Firewalls
By default MinIO uses the port 9000 to listen for incoming connections. If your platform blocks the port by default, you may need to enable access to the port.
### ufw
For hosts with ufw enabled (Debian based distros), you can use `ufw` command to allow traffic to specific ports. Use below command to allow access to port 9000
```sh
ufw allow 9000
```
Below command enables all incoming traffic to ports ranging from 9000 to 9010.
```sh
ufw allow 9000:9010/tcp
```
### firewall-cmd
For hosts with firewall-cmd enabled (CentOS), you can use `firewall-cmd` command to allow traffic to specific ports. Use below commands to allow access to port 9000
```sh
firewall-cmd --get-active-zones
```
This command gets the active zone(s). Now, apply port rules to the relevant zones returned above. For example if the zone is `public`, use
```sh
firewall-cmd --zone=public --add-port=9000/tcp --permanent
```
> [!NOTE]
> `permanent` makes sure the rules are persistent across firewall start, restart or reload. Finally reload the firewall for changes to take effect.
```sh
firewall-cmd --reload
```
### iptables
For hosts with iptables enabled (RHEL, CentOS, etc), you can use `iptables` command to enable all traffic coming to specific ports. Use below command to allow
access to port 9000
```sh
iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
service iptables restart
```
Below command enables all incoming traffic to ports ranging from 9000 to 9010.
```sh
iptables -A INPUT -p tcp --dport 9000:9010 -j ACCEPT
service iptables restart
```
> Production environments using compiled-from-source MinIO binaries do so at their own risk.
> The AGPLv3 license provides no warranties nor liabilites for any such usage.
## Test MinIO Connectivity
### Test using MinIO Console
MinIO Server comes with an embedded web based object browser. Point your web browser to <http://127.0.0.1:9000> to ensure your server has started successfully.
MinIO Server comes with an embedded web based object browser.
Point your web browser to <http://127.0.0.1:9000> to ensure your server has started successfully.
> [!NOTE]
> MinIO runs console on random port by default, if you wish to choose a specific port use `--console-address` to pick a specific interface and port.
### Things to consider
### Test using MinIO Client `mc`
MinIO redirects browser access requests to the configured server port (i.e. `127.0.0.1:9000`) to the configured Console port. MinIO uses the hostname or IP address specified in the request when building the redirect URL. The URL and port *must* be accessible by the client for the redirection to work.
`mc` provides a modern alternative to UNIX commands like ls, cat, cp, mirror, diff etc. It supports filesystems and Amazon S3 compatible cloud storage services.
For deployments behind a load balancer, proxy, or ingress rule where the MinIO host IP address or port is not public, use the `MINIO_BROWSER_REDIRECT_URL` environment variable to specify the external hostname for the redirect. The LB/Proxy must have rules for directing traffic to the Console port specifically.
For example, consider a MinIO deployment behind a proxy `https://minio.example.net`, `https://console.minio.example.net` with rules for forwarding traffic on port :9000 and :9001 to MinIO and the MinIO Console respectively on the internal network. Set `MINIO_BROWSER_REDIRECT_URL` to `https://console.minio.example.net` to ensure the browser receives a valid reachable URL.
| Dashboard | Creating a bucket |
| ------------- | ------------- |
| ![Dashboard](https://github.com/minio/minio/blob/master/docs/screenshots/pic1.png?raw=true) | ![Dashboard](https://github.com/minio/minio/blob/master/docs/screenshots/pic2.png?raw=true) |
## Test using MinIO Client `mc`
`mc` provides a modern alternative to UNIX commands like ls, cat, cp, mirror, diff etc. It supports filesystems and Amazon S3 compatible cloud storage services. Follow the MinIO Client [Quickstart Guide](https://min.io/docs/minio/linux/reference/minio-mc.html#quickstart) for further instructions.
## Upgrading MinIO
Upgrades require zero downtime in MinIO, all upgrades are non-disruptive, all transactions on MinIO are atomic. So upgrading all the servers simultaneously is the recommended way to upgrade MinIO.
> [!NOTE]
> requires internet access to update directly from <https://dl.min.io>, optionally you can host any mirrors at <https://my-artifactory.example.com/minio/>
- For deployments that installed the MinIO server binary by hand, use [`mc admin update`](https://min.io/docs/minio/linux/reference/minio-mc-admin/mc-admin-update.html)
The following commands set a local alias, validate the server information, create a bucket, copy data to that bucket, and list the contents of the bucket.
```sh
mc admin update <minio alias, e.g., myminio>
mc alias set local http://localhost:9000 minioadmin minioadmin
mc admin info
mc mb data
mc cp ~/Downloads/mydata data/
mc ls data/
```
- For deployments without external internet access (e.g. airgapped environments), download the binary from <https://dl.min.io> and replace the existing MinIO binary let's say for example `/opt/bin/minio`, apply executable permissions `chmod +x /opt/bin/minio` and proceed to perform `mc admin service restart alias/`.
- For installations using Systemd MinIO service, upgrade via RPM/DEB packages **parallelly** on all servers or replace the binary lets say `/opt/bin/minio` on all nodes, apply executable permissions `chmod +x /opt/bin/minio` and process to perform `mc admin service restart alias/`.
### Upgrade Checklist
- Test all upgrades in a lower environment (DEV, QA, UAT) before applying to production. Performing blind upgrades in production environments carries significant risk.
- Read the release notes for MinIO *before* performing any upgrade, there is no forced requirement to upgrade to latest release upon every release. Some release may not be relevant to your setup, avoid upgrading production environments unnecessarily.
- If you plan to use `mc admin update`, MinIO process must have write access to the parent directory where the binary is present on the host system.
- `mc admin update` is not supported and should be avoided in kubernetes/container environments, please upgrade containers by upgrading relevant container images.
- **We do not recommend upgrading one MinIO server at a time, the product is designed to support parallel upgrades please follow our recommended guidelines.**
Follow the MinIO Client [Quickstart Guide](https://docs.min.io/community/minio-object-store/reference/minio-mc.html#quickstart) for further instructions.
## Explore Further
- [MinIO Erasure Code Overview](https://min.io/docs/minio/linux/operations/concepts/erasure-coding.html)
- [Use `mc` with MinIO Server](https://min.io/docs/minio/linux/reference/minio-mc.html)
- [Use `minio-go` SDK with MinIO Server](https://min.io/docs/minio/linux/developers/go/minio-go.html)
- [The MinIO documentation website](https://min.io/docs/minio/linux/index.html)
- [The MinIO documentation website](https://docs.min.io/community/minio-object-store/index.html)
- [MinIO Erasure Code Overview](https://docs.min.io/community/minio-object-store/operations/concepts/erasure-coding.html)
- [Use `mc` with MinIO Server](https://docs.min.io/community/minio-object-store/reference/minio-mc.html)
- [Use `minio-go` SDK with MinIO Server](https://docs.min.io/community/minio-object-store/developers/go/minio-go.html)
## Contribute to MinIO Project
Please follow MinIO [Contributor's Guide](https://github.com/minio/minio/blob/master/CONTRIBUTING.md)
Please follow MinIO [Contributor's Guide](https://github.com/minio/minio/blob/master/CONTRIBUTING.md) for guidance on making new contributions to the repository.
## License

View File

@ -193,27 +193,27 @@ func (a adminAPIHandlers) SetConfigKVHandler(w http.ResponseWriter, r *http.Requ
func setConfigKV(ctx context.Context, objectAPI ObjectLayer, kvBytes []byte) (result setConfigResult, err error) {
result.Cfg, err = readServerConfig(ctx, objectAPI, nil)
if err != nil {
return
return result, err
}
result.Dynamic, err = result.Cfg.ReadConfig(bytes.NewReader(kvBytes))
if err != nil {
return
return result, err
}
result.SubSys, _, _, err = config.GetSubSys(string(kvBytes))
if err != nil {
return
return result, err
}
tgts, err := config.ParseConfigTargetID(bytes.NewReader(kvBytes))
if err != nil {
return
return result, err
}
ctx = context.WithValue(ctx, config.ContextKeyForTargetFromConfig, tgts)
if verr := validateConfig(ctx, result.Cfg, result.SubSys); verr != nil {
err = badConfigErr{Err: verr}
return
return result, err
}
// Check if subnet proxy being set and if so set the same value to proxy of subnet
@ -222,12 +222,12 @@ func setConfigKV(ctx context.Context, objectAPI ObjectLayer, kvBytes []byte) (re
// Update the actual server config on disk.
if err = saveServerConfig(ctx, objectAPI, result.Cfg); err != nil {
return
return result, err
}
// Write the config input KV to history.
err = saveServerConfigHistory(ctx, objectAPI, kvBytes)
return
return result, err
}
// GetConfigKVHandler - GET /minio/admin/v3/get-config-kv?key={key}

View File

@ -445,8 +445,10 @@ func (a adminAPIHandlers) ListAccessKeysLDAP(w http.ResponseWriter, r *http.Requ
for _, svc := range serviceAccounts {
expiryTime := svc.Expiration
serviceAccountList = append(serviceAccountList, madmin.ServiceAccountInfo{
AccessKey: svc.AccessKey,
Expiration: &expiryTime,
AccessKey: svc.AccessKey,
Expiration: &expiryTime,
Name: svc.Name,
Description: svc.Description,
})
}
for _, sts := range stsKeys {
@ -625,8 +627,10 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
}
for _, svc := range serviceAccounts {
accessKeys.ServiceAccounts = append(accessKeys.ServiceAccounts, madmin.ServiceAccountInfo{
AccessKey: svc.AccessKey,
Expiration: &svc.Expiration,
AccessKey: svc.AccessKey,
Expiration: &svc.Expiration,
Name: svc.Name,
Description: svc.Description,
})
}
// if only service accounts, skip if user has no service accounts

View File

@ -173,6 +173,8 @@ func (a adminAPIHandlers) ListAccessKeysOpenIDBulk(w http.ResponseWriter, r *htt
if _, ok := accessKey.Claims[iamPolicyClaimNameOpenID()]; !ok {
continue // skip if no roleArn and no policy claim
}
// claim-based provider is in the roleArnMap under dummy ARN
arn = dummyRoleARN
}
matchingCfgName, ok := roleArnMap[arn]
if !ok {

View File

@ -61,7 +61,7 @@ func (a adminAPIHandlers) StartDecommission(w http.ResponseWriter, r *http.Reque
return
}
if z.IsRebalanceStarted() {
if z.IsRebalanceStarted(ctx) {
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminRebalanceAlreadyStarted), r.URL)
return
}
@ -277,7 +277,7 @@ func (a adminAPIHandlers) RebalanceStart(w http.ResponseWriter, r *http.Request)
return
}
if pools.IsRebalanceStarted() {
if pools.IsRebalanceStarted(ctx) {
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminRebalanceAlreadyStarted), r.URL)
return
}
@ -380,7 +380,7 @@ func (a adminAPIHandlers) RebalanceStop(w http.ResponseWriter, r *http.Request)
func proxyDecommissionRequest(ctx context.Context, defaultEndPoint Endpoint, w http.ResponseWriter, r *http.Request) (proxy bool) {
host := env.Get("_MINIO_DECOM_ENDPOINT_HOST", defaultEndPoint.Host)
if host == "" {
return
return proxy
}
for nodeIdx, proxyEp := range globalProxyEndpoints {
if proxyEp.Host == host && !proxyEp.IsLocal {
@ -389,5 +389,5 @@ func proxyDecommissionRequest(ctx context.Context, defaultEndPoint Endpoint, w h
}
}
}
return
return proxy
}

View File

@ -70,7 +70,7 @@ func (a adminAPIHandlers) SiteReplicationAdd(w http.ResponseWriter, r *http.Requ
func getSRAddOptions(r *http.Request) (opts madmin.SRAddOptions) {
opts.ReplicateILMExpiry = r.Form.Get("replicateILMExpiry") == "true"
return
return opts
}
// SRPeerJoin - PUT /minio/admin/v3/site-replication/join
@ -304,7 +304,7 @@ func (a adminAPIHandlers) SRPeerGetIDPSettings(w http.ResponseWriter, r *http.Re
}
}
func parseJSONBody(ctx context.Context, body io.Reader, v interface{}, encryptionKey string) error {
func parseJSONBody(ctx context.Context, body io.Reader, v any, encryptionKey string) error {
data, err := io.ReadAll(body)
if err != nil {
return SRError{
@ -422,7 +422,7 @@ func (a adminAPIHandlers) SiteReplicationEdit(w http.ResponseWriter, r *http.Req
func getSREditOptions(r *http.Request) (opts madmin.SREditOptions) {
opts.DisableILMExpiryReplication = r.Form.Get("disableILMExpiryReplication") == "true"
opts.EnableILMExpiryReplication = r.Form.Get("enableILMExpiryReplication") == "true"
return
return opts
}
// SRPeerEdit - PUT /minio/admin/v3/site-replication/peer/edit
@ -484,7 +484,7 @@ func getSRStatusOptions(r *http.Request) (opts madmin.SRStatusOptions) {
opts.EntityValue = q.Get("entityvalue")
opts.ShowDeleted = q.Get("showDeleted") == "true"
opts.Metrics = q.Get("metrics") == "true"
return
return opts
}
// SiteReplicationRemove - PUT /minio/admin/v3/site-replication/remove

View File

@ -89,7 +89,7 @@ func (s *TestSuiteIAM) TestDeleteUserRace(c *check) {
// Create a policy policy
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -104,7 +104,7 @@ func (s *TestSuiteIAM) TestDeleteUserRace(c *check) {
]
}
]
}`, bucket))
}`, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -113,7 +113,7 @@ func (s *TestSuiteIAM) TestDeleteUserRace(c *check) {
userCount := 50
accessKeys := make([]string, userCount)
secretKeys := make([]string, userCount)
for i := 0; i < userCount; i++ {
for i := range userCount {
accessKey, secretKey := mustGenerateCredentials(c)
err = s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled)
if err != nil {
@ -133,7 +133,7 @@ func (s *TestSuiteIAM) TestDeleteUserRace(c *check) {
}
g := errgroup.Group{}
for i := 0; i < userCount; i++ {
for i := range userCount {
g.Go(func(i int) func() error {
return func() error {
uClient := s.getUserClient(c, accessKeys[i], secretKeys[i], "")

View File

@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/http"
"os"
"slices"
@ -157,9 +158,7 @@ func (a adminAPIHandlers) ListUsers(w http.ResponseWriter, r *http.Request) {
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
return
}
for k, v := range ldapUsers {
allCredentials[k] = v
}
maps.Copy(allCredentials, ldapUsers)
// Marshal the response
data, err := json.Marshal(allCredentials)
@ -2949,7 +2948,7 @@ func commonAddServiceAccount(r *http.Request, ldap bool) (context.Context, auth.
name: createReq.Name,
description: description,
expiration: createReq.Expiration,
claims: make(map[string]interface{}),
claims: make(map[string]any),
}
condValues := getConditionValues(r, "", cred)

View File

@ -332,7 +332,7 @@ func (s *TestSuiteIAM) TestUserPolicyEscalationBug(c *check) {
// 2.2 create and associate policy to user
policy := "mypolicy-test-user-update"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -355,7 +355,7 @@ func (s *TestSuiteIAM) TestUserPolicyEscalationBug(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -562,7 +562,7 @@ func (s *TestSuiteIAM) TestPolicyCreate(c *check) {
// 1. Create a policy
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -585,7 +585,7 @@ func (s *TestSuiteIAM) TestPolicyCreate(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -680,7 +680,7 @@ func (s *TestSuiteIAM) TestCannedPolicies(c *check) {
c.Fatalf("bucket creat error: %v", err)
}
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -703,7 +703,7 @@ func (s *TestSuiteIAM) TestCannedPolicies(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
// Check that default policies can be overwritten.
err = s.adm.AddCannedPolicy(ctx, "readwrite", policyBytes)
@ -739,7 +739,7 @@ func (s *TestSuiteIAM) TestGroupAddRemove(c *check) {
}
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -762,7 +762,7 @@ func (s *TestSuiteIAM) TestGroupAddRemove(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -911,7 +911,7 @@ func (s *TestSuiteIAM) TestServiceAccountOpsByUser(c *check) {
// Create policy, user and associate policy
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -934,7 +934,7 @@ func (s *TestSuiteIAM) TestServiceAccountOpsByUser(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -995,7 +995,7 @@ func (s *TestSuiteIAM) TestServiceAccountDurationSecondsCondition(c *check) {
// Create policy, user and associate policy
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -1026,7 +1026,7 @@ func (s *TestSuiteIAM) TestServiceAccountDurationSecondsCondition(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -1093,7 +1093,7 @@ func (s *TestSuiteIAM) TestServiceAccountOpsByAdmin(c *check) {
// Create policy, user and associate policy
policy := "mypolicy"
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -1116,7 +1116,7 @@ func (s *TestSuiteIAM) TestServiceAccountOpsByAdmin(c *check) {
]
}
]
}`, bucket, bucket))
}`, bucket, bucket)
err = s.adm.AddCannedPolicy(ctx, policy, policyBytes)
if err != nil {
c.Fatalf("policy add error: %v", err)
@ -1367,7 +1367,7 @@ func (s *TestSuiteIAM) TestAccMgmtPlugin(c *check) {
svcAK, svcSK := mustGenerateCredentials(c)
// This policy does not allow listing objects.
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -1381,7 +1381,7 @@ func (s *TestSuiteIAM) TestAccMgmtPlugin(c *check) {
]
}
]
}`, bucket))
}`, bucket)
cr, err := userAdmClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{
Policy: policyBytes,
TargetUser: accessKey,
@ -1558,7 +1558,7 @@ func (c *check) mustDownload(ctx context.Context, client *minio.Client, bucket s
func (c *check) mustUploadReturnVersions(ctx context.Context, client *minio.Client, bucket string) []string {
c.Helper()
versions := []string{}
for i := 0; i < 5; i++ {
for range 5 {
ui, err := client.PutObject(ctx, bucket, "some-object", bytes.NewBuffer([]byte("stuff")), 5, minio.PutObjectOptions{})
if err != nil {
c.Fatalf("upload did not succeed got %#v", err)
@ -1627,7 +1627,7 @@ func (c *check) assertSvcAccSessionPolicyUpdate(ctx context.Context, s *TestSuit
svcAK, svcSK := mustGenerateCredentials(c)
// This policy does not allow listing objects.
policyBytes := []byte(fmt.Sprintf(`{
policyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -1641,7 +1641,7 @@ func (c *check) assertSvcAccSessionPolicyUpdate(ctx context.Context, s *TestSuit
]
}
]
}`, bucket))
}`, bucket)
cr, err := madmClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{
Policy: policyBytes,
TargetUser: accessKey,
@ -1655,7 +1655,7 @@ func (c *check) assertSvcAccSessionPolicyUpdate(ctx context.Context, s *TestSuit
c.mustNotListObjects(ctx, svcClient, bucket)
// This policy allows listing objects.
newPolicyBytes := []byte(fmt.Sprintf(`{
newPolicyBytes := fmt.Appendf(nil, `{
"Version": "2012-10-17",
"Statement": [
{
@ -1668,7 +1668,7 @@ func (c *check) assertSvcAccSessionPolicyUpdate(ctx context.Context, s *TestSuit
]
}
]
}`, bucket))
}`, bucket)
err = madmClient.UpdateServiceAccount(ctx, svcAK, madmin.UpdateServiceAccountReq{
NewPolicy: newPolicyBytes,
})

View File

@ -954,7 +954,7 @@ func (a adminAPIHandlers) ForceUnlockHandler(w http.ResponseWriter, r *http.Requ
var args dsync.LockArgs
var lockers []dsync.NetLocker
for _, path := range strings.Split(vars["paths"], ",") {
for path := range strings.SplitSeq(vars["paths"], ",") {
if path == "" {
continue
}
@ -1193,7 +1193,7 @@ type dummyFileInfo struct {
mode os.FileMode
modTime time.Time
isDir bool
sys interface{}
sys any
}
func (f dummyFileInfo) Name() string { return f.name }
@ -1201,7 +1201,7 @@ func (f dummyFileInfo) Size() int64 { return f.size }
func (f dummyFileInfo) Mode() os.FileMode { return f.mode }
func (f dummyFileInfo) ModTime() time.Time { return f.modTime }
func (f dummyFileInfo) IsDir() bool { return f.isDir }
func (f dummyFileInfo) Sys() interface{} { return f.sys }
func (f dummyFileInfo) Sys() any { return f.sys }
// DownloadProfilingHandler - POST /minio/admin/v3/profiling/download
// ----------
@ -1243,17 +1243,17 @@ func extractHealInitParams(vars map[string]string, qParams url.Values, r io.Read
if hip.objPrefix != "" {
// Bucket is required if object-prefix is given
err = ErrHealMissingBucket
return
return hip, err
}
} else if isReservedOrInvalidBucket(hip.bucket, false) {
err = ErrInvalidBucketName
return
return hip, err
}
// empty prefix is valid.
if !IsValidObjectPrefix(hip.objPrefix) {
err = ErrInvalidObjectName
return
return hip, err
}
if len(qParams[mgmtClientToken]) > 0 {
@ -1275,7 +1275,7 @@ func extractHealInitParams(vars map[string]string, qParams url.Values, r io.Read
if (hip.forceStart && hip.forceStop) ||
(hip.clientToken != "" && (hip.forceStart || hip.forceStop)) {
err = ErrInvalidRequest
return
return hip, err
}
// ignore body if clientToken is provided
@ -1284,12 +1284,12 @@ func extractHealInitParams(vars map[string]string, qParams url.Values, r io.Read
if jerr != nil {
adminLogIf(GlobalContext, jerr, logger.ErrorKind)
err = ErrRequestBodyParse
return
return hip, err
}
}
err = ErrNone
return
return hip, err
}
// HealHandler - POST /minio/admin/v3/heal/
@ -2022,7 +2022,7 @@ func extractTraceOptions(r *http.Request) (opts madmin.ServiceTraceOpts, err err
opts.OS = true
// Older mc - cannot deal with more types...
}
return
return opts, err
}
// TraceHandler - POST /minio/admin/v3/trace

View File

@ -402,7 +402,7 @@ func (b byResourceUID) Less(i, j int) bool {
func TestTopLockEntries(t *testing.T) {
locksHeld := make(map[string][]lockRequesterInfo)
var owners []string
for i := 0; i < 4; i++ {
for i := range 4 {
owners = append(owners, fmt.Sprintf("node-%d", i))
}
@ -410,7 +410,7 @@ func TestTopLockEntries(t *testing.T) {
// request UID, but 10 different resource names associated with it.
var lris []lockRequesterInfo
uuid := mustGetUUID()
for i := 0; i < 10; i++ {
for i := range 10 {
resource := fmt.Sprintf("bucket/delete-object-%d", i)
lri := lockRequesterInfo{
Name: resource,
@ -425,7 +425,7 @@ func TestTopLockEntries(t *testing.T) {
}
// Add a few concurrent read locks to the mix
for i := 0; i < 50; i++ {
for i := range 50 {
resource := fmt.Sprintf("bucket/get-object-%d", i)
lri := lockRequesterInfo{
Name: resource,

View File

@ -22,6 +22,7 @@ import (
"encoding/json"
"errors"
"fmt"
"maps"
"net/http"
"sort"
"sync"
@ -520,9 +521,7 @@ func (h *healSequence) getScannedItemsMap() map[madmin.HealItemType]int64 {
// Make a copy before returning the value
retMap := make(map[madmin.HealItemType]int64, len(h.scannedItemsMap))
for k, v := range h.scannedItemsMap {
retMap[k] = v
}
maps.Copy(retMap, h.scannedItemsMap)
return retMap
}
@ -534,9 +533,7 @@ func (h *healSequence) getHealedItemsMap() map[madmin.HealItemType]int64 {
// Make a copy before returning the value
retMap := make(map[madmin.HealItemType]int64, len(h.healedItemsMap))
for k, v := range h.healedItemsMap {
retMap[k] = v
}
maps.Copy(retMap, h.healedItemsMap)
return retMap
}
@ -549,9 +546,7 @@ func (h *healSequence) getHealFailedItemsMap() map[madmin.HealItemType]int64 {
// Make a copy before returning the value
retMap := make(map[madmin.HealItemType]int64, len(h.healFailedItemsMap))
for k, v := range h.healFailedItemsMap {
retMap[k] = v
}
maps.Copy(retMap, h.healFailedItemsMap)
return retMap
}

View File

@ -65,7 +65,7 @@ func setCommonHeaders(w http.ResponseWriter) {
}
// Encodes the response headers into XML format.
func encodeResponse(response interface{}) []byte {
func encodeResponse(response any) []byte {
var buf bytes.Buffer
buf.WriteString(xml.Header)
if err := xml.NewEncoder(&buf).Encode(response); err != nil {
@ -83,7 +83,7 @@ func encodeResponse(response interface{}) []byte {
// Do not use this function for anything other than ListObjects()
// variants, please open a github discussion if you wish to use
// this in other places.
func encodeResponseList(response interface{}) []byte {
func encodeResponseList(response any) []byte {
var buf bytes.Buffer
buf.WriteString(xxml.Header)
if err := xxml.NewEncoder(&buf).Encode(response); err != nil {
@ -94,7 +94,7 @@ func encodeResponseList(response interface{}) []byte {
}
// Encodes the response headers into JSON format.
func encodeResponseJSON(response interface{}) []byte {
func encodeResponseJSON(response any) []byte {
var bytesBuffer bytes.Buffer
e := json.NewEncoder(&bytesBuffer)
e.Encode(response)

View File

@ -31,7 +31,7 @@ func getListObjectsV1Args(values url.Values) (prefix, marker, delimiter string,
var err error
if maxkeys, err = strconv.Atoi(values.Get("max-keys")); err != nil {
errCode = ErrInvalidMaxKeys
return
return prefix, marker, delimiter, maxkeys, encodingType, errCode
}
} else {
maxkeys = maxObjectList
@ -41,7 +41,7 @@ func getListObjectsV1Args(values url.Values) (prefix, marker, delimiter string,
marker = values.Get("marker")
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")
return
return prefix, marker, delimiter, maxkeys, encodingType, errCode
}
func getListBucketObjectVersionsArgs(values url.Values) (prefix, marker, delimiter string, maxkeys int, encodingType, versionIDMarker string, errCode APIErrorCode) {
@ -51,7 +51,7 @@ func getListBucketObjectVersionsArgs(values url.Values) (prefix, marker, delimit
var err error
if maxkeys, err = strconv.Atoi(values.Get("max-keys")); err != nil {
errCode = ErrInvalidMaxKeys
return
return prefix, marker, delimiter, maxkeys, encodingType, versionIDMarker, errCode
}
} else {
maxkeys = maxObjectList
@ -62,7 +62,7 @@ func getListBucketObjectVersionsArgs(values url.Values) (prefix, marker, delimit
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")
versionIDMarker = values.Get("version-id-marker")
return
return prefix, marker, delimiter, maxkeys, encodingType, versionIDMarker, errCode
}
// Parse bucket url queries for ListObjects V2.
@ -73,7 +73,7 @@ func getListObjectsV2Args(values url.Values) (prefix, token, startAfter, delimit
if val, ok := values["continuation-token"]; ok {
if len(val[0]) == 0 {
errCode = ErrIncorrectContinuationToken
return
return prefix, token, startAfter, delimiter, fetchOwner, maxkeys, encodingType, errCode
}
}
@ -81,7 +81,7 @@ func getListObjectsV2Args(values url.Values) (prefix, token, startAfter, delimit
var err error
if maxkeys, err = strconv.Atoi(values.Get("max-keys")); err != nil {
errCode = ErrInvalidMaxKeys
return
return prefix, token, startAfter, delimiter, fetchOwner, maxkeys, encodingType, errCode
}
} else {
maxkeys = maxObjectList
@ -97,11 +97,11 @@ func getListObjectsV2Args(values url.Values) (prefix, token, startAfter, delimit
decodedToken, err := base64.StdEncoding.DecodeString(token)
if err != nil {
errCode = ErrIncorrectContinuationToken
return
return prefix, token, startAfter, delimiter, fetchOwner, maxkeys, encodingType, errCode
}
token = string(decodedToken)
}
return
return prefix, token, startAfter, delimiter, fetchOwner, maxkeys, encodingType, errCode
}
// Parse bucket url queries for ?uploads
@ -112,7 +112,7 @@ func getBucketMultipartResources(values url.Values) (prefix, keyMarker, uploadID
var err error
if maxUploads, err = strconv.Atoi(values.Get("max-uploads")); err != nil {
errCode = ErrInvalidMaxUploads
return
return prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, encodingType, errCode
}
} else {
maxUploads = maxUploadsList
@ -123,7 +123,7 @@ func getBucketMultipartResources(values url.Values) (prefix, keyMarker, uploadID
uploadIDMarker = values.Get("upload-id-marker")
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")
return
return prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, encodingType, errCode
}
// Parse object url queries
@ -134,7 +134,7 @@ func getObjectResources(values url.Values) (uploadID string, partNumberMarker, m
if values.Get("max-parts") != "" {
if maxParts, err = strconv.Atoi(values.Get("max-parts")); err != nil {
errCode = ErrInvalidMaxParts
return
return uploadID, partNumberMarker, maxParts, encodingType, errCode
}
} else {
maxParts = maxPartsList
@ -143,11 +143,11 @@ func getObjectResources(values url.Values) (uploadID string, partNumberMarker, m
if values.Get("part-number-marker") != "" {
if partNumberMarker, err = strconv.Atoi(values.Get("part-number-marker")); err != nil {
errCode = ErrInvalidPartNumberMarker
return
return uploadID, partNumberMarker, maxParts, encodingType, errCode
}
}
uploadID = values.Get("uploadId")
encodingType = values.Get("encoding-type")
return
return uploadID, partNumberMarker, maxParts, encodingType, errCode
}

View File

@ -100,7 +100,6 @@ func TestObjectLocation(t *testing.T) {
},
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
gotLocation := getObjectLocation(testCase.request, testCase.domains, testCase.bucket, testCase.object)
if testCase.expectedLocation != gotLocation {

View File

@ -216,7 +216,7 @@ func getSessionToken(r *http.Request) (token string) {
// Fetch claims in the security token returned by the client, doesn't return
// errors - upon errors the returned claims map will be empty.
func mustGetClaimsFromToken(r *http.Request) map[string]interface{} {
func mustGetClaimsFromToken(r *http.Request) map[string]any {
claims, _ := getClaimsFromToken(getSessionToken(r))
return claims
}
@ -266,7 +266,7 @@ func getClaimsFromTokenWithSecret(token, secret string) (*xjwt.MapClaims, error)
}
// Fetch claims in the security token returned by the client.
func getClaimsFromToken(token string) (map[string]interface{}, error) {
func getClaimsFromToken(token string) (map[string]any, error) {
jwtClaims, err := getClaimsFromTokenWithSecret(token, globalActiveCred.SecretKey)
if err != nil {
return nil, err
@ -275,7 +275,7 @@ func getClaimsFromToken(token string) (map[string]interface{}, error) {
}
// Fetch claims in the security token returned by the client and validate the token.
func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]interface{}, APIErrorCode) {
func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]any, APIErrorCode) {
token := getSessionToken(r)
if token != "" && cred.AccessKey == "" {
// x-amz-security-token is not allowed for anonymous access.

View File

@ -24,6 +24,7 @@ import (
"fmt"
"io"
"os"
"slices"
"sort"
"strings"
"sync"
@ -269,12 +270,7 @@ func (h *healingTracker) delete(ctx context.Context) error {
func (h *healingTracker) isHealed(bucket string) bool {
h.mu.RLock()
defer h.mu.RUnlock()
for _, v := range h.HealedBuckets {
if v == bucket {
return true
}
}
return false
return slices.Contains(h.HealedBuckets, bucket)
}
// resume will reset progress to the numbers at the start of the bucket.

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"time"

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -25,6 +25,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"math/rand"
"net/http"
"net/url"
@ -574,9 +575,7 @@ func toObjectInfo(bucket, object string, objInfo minio.ObjectInfo) ObjectInfo {
oi.UserDefined[xhttp.AmzStorageClass] = objInfo.StorageClass
}
for k, v := range objInfo.UserMetadata {
oi.UserDefined[k] = v
}
maps.Copy(oi.UserDefined, objInfo.UserMetadata)
return oi
}

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -275,7 +275,7 @@ func (sf BatchJobSizeFilter) Validate() error {
type BatchJobSize int64
// UnmarshalYAML to parse humanized byte values
func (s *BatchJobSize) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (s *BatchJobSize) UnmarshalYAML(unmarshal func(any) error) error {
var batchExpireSz string
err := unmarshal(&batchExpireSz)
if err != nil {

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -21,6 +21,7 @@ import (
"context"
"encoding/base64"
"fmt"
"maps"
"math/rand"
"net/http"
"runtime"
@ -110,9 +111,7 @@ func (e BatchJobKeyRotateEncryption) Validate() error {
}
}
e.kmsContext = kms.Context{}
for k, v := range ctx {
e.kmsContext[k] = v
}
maps.Copy(e.kmsContext, ctx)
ctx["MinIO batch API"] = "batchrotate" // Context for a test key operation
if _, err := GlobalKMS.GenerateKey(GlobalContext, &kms.GenerateKeyRequest{Name: e.Key, AssociatedData: ctx}); err != nil {
return err
@ -225,9 +224,7 @@ func (r *BatchJobKeyRotateV1) KeyRotate(ctx context.Context, api ObjectLayer, ob
// Since we are rotating the keys, make sure to update the metadata.
oi.metadataOnly = true
oi.keyRotation = true
for k, v := range encMetadata {
oi.UserDefined[k] = v
}
maps.Copy(oi.UserDefined, encMetadata)
if _, err := api.CopyObject(ctx, r.Bucket, oi.Name, r.Bucket, oi.Name, oi, ObjectOptions{
VersionID: oi.VersionID,
}, ObjectOptions{

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -51,8 +51,8 @@ func runPutObjectBenchmark(b *testing.B, obj ObjectLayer, objSize int) {
// benchmark utility which helps obtain number of allocations and bytes allocated per ops.
b.ReportAllocs()
// the actual benchmark for PutObject starts here. Reset the benchmark timer.
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 0; b.Loop(); i++ {
// insert the object.
objInfo, err := obj.PutObject(b.Context(), bucket, "object"+strconv.Itoa(i),
mustGetPutObjReader(b, bytes.NewReader(textData), int64(len(textData)), md5hex, sha256hex), ObjectOptions{})
@ -101,11 +101,11 @@ func runPutObjectPartBenchmark(b *testing.B, obj ObjectLayer, partSize int) {
// benchmark utility which helps obtain number of allocations and bytes allocated per ops.
b.ReportAllocs()
// the actual benchmark for PutObjectPart starts here. Reset the benchmark timer.
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 0; b.Loop(); i++ {
// insert the object.
totalPartsNR := int(math.Ceil(float64(objSize) / float64(partSize)))
for j := 0; j < totalPartsNR; j++ {
for j := range totalPartsNR {
if j < totalPartsNR-1 {
textPartData = textData[j*partSize : (j+1)*partSize-1]
} else {

View File

@ -99,7 +99,7 @@ func BitrotAlgorithmFromString(s string) (a BitrotAlgorithm) {
return alg
}
}
return
return a
}
func newBitrotWriter(disk StorageAPI, origvolume, volume, filePath string, length int64, algo BitrotAlgorithm, shardSize int64) io.Writer {

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)
@ -59,19 +59,17 @@ func (z *ServerSystemConfig) DecodeMsg(dc *msgp.Reader) (err error) {
if z.MinioEnv == nil {
z.MinioEnv = make(map[string]string, zb0003)
} else if len(z.MinioEnv) > 0 {
for key := range z.MinioEnv {
delete(z.MinioEnv, key)
}
clear(z.MinioEnv)
}
for zb0003 > 0 {
zb0003--
var za0002 string
var za0003 string
za0002, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "MinioEnv")
return
}
var za0003 string
za0003, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "MinioEnv", za0002)
@ -240,14 +238,12 @@ func (z *ServerSystemConfig) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.MinioEnv == nil {
z.MinioEnv = make(map[string]string, zb0003)
} else if len(z.MinioEnv) > 0 {
for key := range z.MinioEnv {
delete(z.MinioEnv, key)
}
clear(z.MinioEnv)
}
for zb0003 > 0 {
var za0002 string
var za0003 string
zb0003--
var za0002 string
za0002, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "MinioEnv")

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -154,7 +154,6 @@ func initFederatorBackend(buckets []string, objLayer ObjectLayer) {
g := errgroup.WithNErrs(len(bucketsToBeUpdatedSlice)).WithConcurrency(50)
for index := range bucketsToBeUpdatedSlice {
index := index
g.Go(func() error {
return globalDNSConfig.Put(bucketsToBeUpdatedSlice[index])
}, index)
@ -593,7 +592,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
output[idx] = obj
idx++
}
return
return output
}
// Disable timeouts and cancellation
@ -1387,10 +1386,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
// Set the correct hex md5sum for the fan-out stream.
fanOutOpts.MD5Hex = hex.EncodeToString(md5w.Sum(nil))
concurrentSize := 100
if runtime.GOMAXPROCS(0) < concurrentSize {
concurrentSize = runtime.GOMAXPROCS(0)
}
concurrentSize := min(runtime.GOMAXPROCS(0), 100)
fanOutResp := make([]minio.PutObjectFanOutResponse, 0, len(fanOutEntries))
eventArgsList := make([]eventArgs, 0, len(fanOutEntries))
@ -1661,9 +1657,11 @@ func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Re
return
}
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(s3Error))
return
if s3Error := checkRequestAuthType(ctx, r, policy.HeadBucketAction, bucket, ""); s3Error != ErrNone {
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(s3Error))
return
}
}
getBucketInfo := objectAPI.GetBucketInfo

View File

@ -657,7 +657,7 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
sha256sum := ""
var objectNames []string
for i := 0; i < 10; i++ {
for i := range 10 {
contentBytes := []byte("hello")
objectName := "test-object-" + strconv.Itoa(i)
if i == 0 {
@ -687,7 +687,7 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
// The following block will create a bucket policy with delete object to 'public/*'. This is
// to test a mixed response of a successful & failure while deleting objects in a single request
policyBytes := []byte(fmt.Sprintf(`{"Id": "Policy1637752602639", "Version": "2012-10-17", "Statement": [{"Sid": "Stmt1637752600730", "Action": "s3:DeleteObject", "Effect": "Allow", "Resource": "arn:aws:s3:::%s/public/*", "Principal": "*"}]}`, bucketName))
policyBytes := fmt.Appendf(nil, `{"Id": "Policy1637752602639", "Version": "2012-10-17", "Statement": [{"Sid": "Stmt1637752600730", "Action": "s3:DeleteObject", "Effect": "Allow", "Resource": "arn:aws:s3:::%s/public/*", "Principal": "*"}]}`, bucketName)
rec := httptest.NewRecorder()
req, err := newTestSignedRequestV4(http.MethodPut, getPutPolicyURL("", bucketName), int64(len(policyBytes)), bytes.NewReader(policyBytes),
credentials.AccessKey, credentials.SecretKey, nil)

View File

@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/http"
"strconv"
"strings"
@ -959,9 +960,7 @@ func putRestoreOpts(bucket, object string, rreq *RestoreObjectRequest, objInfo O
UserDefined: meta,
}
}
for k, v := range objInfo.UserDefined {
meta[k] = v
}
maps.Copy(meta, objInfo.UserDefined)
if len(objInfo.UserTags) != 0 {
meta[xhttp.AmzObjectTagging] = objInfo.UserTags
}

View File

@ -248,19 +248,19 @@ func proxyRequestByToken(ctx context.Context, w http.ResponseWriter, r *http.Req
if subToken, nodeIndex = parseRequestToken(token); nodeIndex >= 0 {
proxied, success = proxyRequestByNodeIndex(ctx, w, r, nodeIndex, returnErr)
}
return
return subToken, proxied, success
}
func proxyRequestByNodeIndex(ctx context.Context, w http.ResponseWriter, r *http.Request, index int, returnErr bool) (proxied, success bool) {
if len(globalProxyEndpoints) == 0 {
return
return proxied, success
}
if index < 0 || index >= len(globalProxyEndpoints) {
return
return proxied, success
}
ep := globalProxyEndpoints[index]
if ep.IsLocal {
return
return proxied, success
}
return true, proxyRequest(ctx, w, r, ep, returnErr)
}

View File

@ -472,7 +472,7 @@ func (sys *BucketMetadataSys) GetConfig(ctx context.Context, bucket string) (met
return meta, reloaded, nil
}
val, err, _ := sys.group.Do(bucket, func() (val interface{}, err error) {
val, err, _ := sys.group.Do(bucket, func() (val any, err error) {
meta, err = loadBucketMetadata(ctx, objAPI, bucket)
if err != nil {
if !sys.Initialized() {
@ -511,7 +511,6 @@ func (sys *BucketMetadataSys) concurrentLoad(ctx context.Context, buckets []stri
g := errgroup.WithNErrs(len(buckets))
bucketMetas := make([]BucketMetadata, len(buckets))
for index := range buckets {
index := index
g.Go(func() error {
// Sleep and stagger to avoid blocked CPU and thundering
// herd upon start up sequence.

View File

@ -161,7 +161,7 @@ func (b BucketMetadata) lastUpdate() (t time.Time) {
t = b.BucketTargetsConfigMetaUpdatedAt
}
return
return t
}
// Versioning returns true if versioning is enabled
@ -542,13 +542,13 @@ func (b *BucketMetadata) migrateTargetConfig(ctx context.Context, objectAPI Obje
func encryptBucketMetadata(ctx context.Context, bucket string, input []byte, kmsContext kms.Context) (output, metabytes []byte, err error) {
if GlobalKMS == nil {
output = input
return
return output, metabytes, err
}
metadata := make(map[string]string)
key, err := GlobalKMS.GenerateKey(ctx, &kms.GenerateKeyRequest{AssociatedData: kmsContext})
if err != nil {
return
return output, metabytes, err
}
outbuf := bytes.NewBuffer(nil)
@ -561,7 +561,7 @@ func encryptBucketMetadata(ctx context.Context, bucket string, input []byte, kms
}
metabytes, err = json.Marshal(metadata)
if err != nil {
return
return output, metabytes, err
}
return outbuf.Bytes(), metabytes, nil
}

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -297,6 +297,9 @@ func checkPutObjectLockAllowed(ctx context.Context, rq *http.Request, bucket, ob
if legalHold, lerr = objectlock.ParseObjectLockLegalHoldHeaders(rq.Header); lerr != nil {
return mode, retainDate, legalHold, toAPIErrorCode(ctx, lerr)
}
if legalHoldPermErr != ErrNone {
return mode, retainDate, legalHold, legalHoldPermErr
}
}
if retentionRequested {

View File

@ -122,7 +122,7 @@ func testCreateBucket(obj ObjectLayer, instanceType, bucketName string, apiRoute
var wg sync.WaitGroup
var mu sync.Mutex
wg.Add(n)
for i := 0; i < n; i++ {
for range n {
go func() {
defer wg.Done()
// Sync start.
@ -187,7 +187,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// Test case - 1.
{
bucketName: bucketName,
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, bucketName, bucketName)),
policyLen: len(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName)),
accessKey: credentials.AccessKey,
@ -199,7 +199,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// Expecting StatusBadRequest (400).
{
bucketName: bucketName,
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, bucketName, bucketName)),
policyLen: maxBucketPolicySize + 1,
accessKey: credentials.AccessKey,
@ -211,7 +211,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// Expecting the HTTP response status to be StatusLengthRequired (411).
{
bucketName: bucketName,
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, bucketName, bucketName)),
policyLen: 0,
accessKey: credentials.AccessKey,
@ -258,7 +258,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// checkBucketPolicyResources should fail.
{
bucketName: bucketName1,
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, bucketName, bucketName)),
policyLen: len(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName)),
accessKey: credentials.AccessKey,
@ -271,7 +271,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// should result in 404 StatusNotFound
{
bucketName: "non-existent-bucket",
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, "non-existent-bucket", "non-existent-bucket"))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, "non-existent-bucket", "non-existent-bucket")),
policyLen: len(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName)),
accessKey: credentials.AccessKey,
@ -284,7 +284,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// should result in 404 StatusNotFound
{
bucketName: ".invalid-bucket",
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplate, ".invalid-bucket", ".invalid-bucket"))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplate, ".invalid-bucket", ".invalid-bucket")),
policyLen: len(fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName)),
accessKey: credentials.AccessKey,
@ -297,7 +297,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string
// should result in 400 StatusBadRequest.
{
bucketName: bucketName,
bucketPolicyReader: bytes.NewReader([]byte(fmt.Sprintf(bucketPolicyTemplateWithoutVersion, bucketName, bucketName))),
bucketPolicyReader: bytes.NewReader(fmt.Appendf(nil, bucketPolicyTemplateWithoutVersion, bucketName, bucketName)),
policyLen: len(fmt.Sprintf(bucketPolicyTemplateWithoutVersion, bucketName, bucketName)),
accessKey: credentials.AccessKey,

View File

@ -19,6 +19,7 @@ package cmd
import (
"encoding/json"
"maps"
"net/http"
"net/url"
"strconv"
@ -187,9 +188,7 @@ func getConditionValues(r *http.Request, lc string, cred auth.Credentials) map[s
}
cloneURLValues := make(url.Values, len(r.Form))
for k, v := range r.Form {
cloneURLValues[k] = v
}
maps.Copy(cloneURLValues, r.Form)
for _, objLock := range []string{
xhttp.AmzObjectLockMode,
@ -224,7 +223,7 @@ func getConditionValues(r *http.Request, lc string, cred auth.Credentials) map[s
// Add groups claim which could be a list. This will ensure that the claim
// `jwt:groups` works.
if grpsVal, ok := claims["groups"]; ok {
if grpsIs, ok := grpsVal.([]interface{}); ok {
if grpsIs, ok := grpsVal.([]any); ok {
grps := []string{}
for _, gI := range grpsIs {
if g, ok := gI.(string); ok {

View File

@ -92,12 +92,12 @@ func parseBucketQuota(bucket string, data []byte) (quotaCfg *madmin.BucketQuota,
}
if !quotaCfg.IsValid() {
if quotaCfg.Type == "fifo" {
internalLogIf(GlobalContext, errors.New("Detected older 'fifo' quota config, 'fifo' feature is removed and not supported anymore. Please clear your quota configs using 'mc admin bucket quota alias/bucket --clear' and use 'mc ilm add' for expiration of objects"), logger.WarningKind)
internalLogIf(GlobalContext, errors.New("Detected older 'fifo' quota config, 'fifo' feature is removed and not supported anymore. Please clear your quota configs using 'mc quota clear alias/bucket' and use 'mc ilm add' for expiration of objects"), logger.WarningKind)
return quotaCfg, fmt.Errorf("invalid quota type 'fifo'")
}
return quotaCfg, fmt.Errorf("Invalid quota config %#v", quotaCfg)
}
return
return quotaCfg, err
}
func (sys *BucketQuotaSys) enforceQuotaHard(ctx context.Context, bucket string, size int64) error {

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -21,6 +21,7 @@ import (
"bytes"
"context"
"fmt"
"maps"
"net/http"
"net/url"
"regexp"
@ -171,13 +172,13 @@ func (ri ReplicateObjectInfo) TargetReplicationStatus(arn string) (status replic
repStatMatches := replStatusRegex.FindAllStringSubmatch(ri.ReplicationStatusInternal, -1)
for _, repStatMatch := range repStatMatches {
if len(repStatMatch) != 3 {
return
return status
}
if repStatMatch[1] == arn {
return replication.StatusType(repStatMatch[2])
}
}
return
return status
}
// TargetReplicationStatus - returns replication status of a target
@ -185,13 +186,13 @@ func (o ObjectInfo) TargetReplicationStatus(arn string) (status replication.Stat
repStatMatches := replStatusRegex.FindAllStringSubmatch(o.ReplicationStatusInternal, -1)
for _, repStatMatch := range repStatMatches {
if len(repStatMatch) != 3 {
return
return status
}
if repStatMatch[1] == arn {
return replication.StatusType(repStatMatch[2])
}
}
return
return status
}
type replicateTargetDecision struct {
@ -309,9 +310,9 @@ func parseReplicateDecision(ctx context.Context, bucket, s string) (r ReplicateD
targetsMap: make(map[string]replicateTargetDecision),
}
if len(s) == 0 {
return
return r, err
}
for _, p := range strings.Split(s, ",") {
for p := range strings.SplitSeq(s, ",") {
if p == "" {
continue
}
@ -326,7 +327,7 @@ func parseReplicateDecision(ctx context.Context, bucket, s string) (r ReplicateD
}
r.targetsMap[slc[0]] = replicateTargetDecision{Replicate: tgt[0] == "true", Synchronous: tgt[1] == "true", Arn: tgt[2], ID: tgt[3]}
}
return
return r, err
}
// ReplicationState represents internal replication state
@ -373,7 +374,7 @@ func (rs *ReplicationState) CompositeReplicationStatus() (st replication.StatusT
case !rs.ReplicaStatus.Empty():
return rs.ReplicaStatus
default:
return
return st
}
}
@ -735,10 +736,8 @@ type BucketReplicationResyncStatus struct {
func (rs *BucketReplicationResyncStatus) cloneTgtStats() (m map[string]TargetReplicationResyncStatus) {
m = make(map[string]TargetReplicationResyncStatus)
for arn, st := range rs.TargetsMap {
m[arn] = st
}
return
maps.Copy(m, rs.TargetsMap)
return m
}
func newBucketResyncStatus(bucket string) BucketReplicationResyncStatus {
@ -775,7 +774,7 @@ func extractReplicateDiffOpts(q url.Values) (opts madmin.ReplDiffOpts) {
opts.Verbose = q.Get("verbose") == "true"
opts.ARN = q.Get("arn")
opts.Prefix = q.Get("prefix")
return
return opts
}
const (

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/minio/minio/internal/bucket/replication"
"github.com/tinylib/msgp/msgp"
@ -41,19 +41,17 @@ func (z *BucketReplicationResyncStatus) DecodeMsg(dc *msgp.Reader) (err error) {
if z.TargetsMap == nil {
z.TargetsMap = make(map[string]TargetReplicationResyncStatus, zb0002)
} else if len(z.TargetsMap) > 0 {
for key := range z.TargetsMap {
delete(z.TargetsMap, key)
}
clear(z.TargetsMap)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 TargetReplicationResyncStatus
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "TargetsMap")
return
}
var za0002 TargetReplicationResyncStatus
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "TargetsMap", za0001)
@ -203,14 +201,12 @@ func (z *BucketReplicationResyncStatus) UnmarshalMsg(bts []byte) (o []byte, err
if z.TargetsMap == nil {
z.TargetsMap = make(map[string]TargetReplicationResyncStatus, zb0002)
} else if len(z.TargetsMap) > 0 {
for key := range z.TargetsMap {
delete(z.TargetsMap, key)
}
clear(z.TargetsMap)
}
for zb0002 > 0 {
var za0001 string
var za0002 TargetReplicationResyncStatus
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "TargetsMap")
@ -288,19 +284,17 @@ func (z *MRFReplicateEntries) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Entries == nil {
z.Entries = make(map[string]MRFReplicateEntry, zb0002)
} else if len(z.Entries) > 0 {
for key := range z.Entries {
delete(z.Entries, key)
}
clear(z.Entries)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 MRFReplicateEntry
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Entries")
return
}
var za0002 MRFReplicateEntry
var zb0003 uint32
zb0003, err = dc.ReadMapHeader()
if err != nil {
@ -478,14 +472,12 @@ func (z *MRFReplicateEntries) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Entries == nil {
z.Entries = make(map[string]MRFReplicateEntry, zb0002)
} else if len(z.Entries) > 0 {
for key := range z.Entries {
delete(z.Entries, key)
}
clear(z.Entries)
}
for zb0002 > 0 {
var za0001 string
var za0002 MRFReplicateEntry
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Entries")
@ -872,19 +864,17 @@ func (z *ReplicationState) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Targets == nil {
z.Targets = make(map[string]replication.StatusType, zb0002)
} else if len(z.Targets) > 0 {
for key := range z.Targets {
delete(z.Targets, key)
}
clear(z.Targets)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 replication.StatusType
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Targets")
return
}
var za0002 replication.StatusType
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Targets", za0001)
@ -902,19 +892,17 @@ func (z *ReplicationState) DecodeMsg(dc *msgp.Reader) (err error) {
if z.PurgeTargets == nil {
z.PurgeTargets = make(map[string]VersionPurgeStatusType, zb0003)
} else if len(z.PurgeTargets) > 0 {
for key := range z.PurgeTargets {
delete(z.PurgeTargets, key)
}
clear(z.PurgeTargets)
}
for zb0003 > 0 {
zb0003--
var za0003 string
var za0004 VersionPurgeStatusType
za0003, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "PurgeTargets")
return
}
var za0004 VersionPurgeStatusType
err = za0004.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "PurgeTargets", za0003)
@ -932,19 +920,17 @@ func (z *ReplicationState) DecodeMsg(dc *msgp.Reader) (err error) {
if z.ResetStatusesMap == nil {
z.ResetStatusesMap = make(map[string]string, zb0004)
} else if len(z.ResetStatusesMap) > 0 {
for key := range z.ResetStatusesMap {
delete(z.ResetStatusesMap, key)
}
clear(z.ResetStatusesMap)
}
for zb0004 > 0 {
zb0004--
var za0005 string
var za0006 string
za0005, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "ResetStatusesMap")
return
}
var za0006 string
za0006, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "ResetStatusesMap", za0005)
@ -1236,14 +1222,12 @@ func (z *ReplicationState) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Targets == nil {
z.Targets = make(map[string]replication.StatusType, zb0002)
} else if len(z.Targets) > 0 {
for key := range z.Targets {
delete(z.Targets, key)
}
clear(z.Targets)
}
for zb0002 > 0 {
var za0001 string
var za0002 replication.StatusType
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Targets")
@ -1266,14 +1250,12 @@ func (z *ReplicationState) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.PurgeTargets == nil {
z.PurgeTargets = make(map[string]VersionPurgeStatusType, zb0003)
} else if len(z.PurgeTargets) > 0 {
for key := range z.PurgeTargets {
delete(z.PurgeTargets, key)
}
clear(z.PurgeTargets)
}
for zb0003 > 0 {
var za0003 string
var za0004 VersionPurgeStatusType
zb0003--
var za0003 string
za0003, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "PurgeTargets")
@ -1296,14 +1278,12 @@ func (z *ReplicationState) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.ResetStatusesMap == nil {
z.ResetStatusesMap = make(map[string]string, zb0004)
} else if len(z.ResetStatusesMap) > 0 {
for key := range z.ResetStatusesMap {
delete(z.ResetStatusesMap, key)
}
clear(z.ResetStatusesMap)
}
for zb0004 > 0 {
var za0005 string
var za0006 string
zb0004--
var za0005 string
za0005, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "ResetStatusesMap")

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"math/rand"
"net/http"
"net/url"
@ -252,31 +253,31 @@ func getMustReplicateOptions(userDefined map[string]string, userTags string, sta
func mustReplicate(ctx context.Context, bucket, object string, mopts mustReplicateOptions) (dsc ReplicateDecision) {
// object layer not initialized we return with no decision.
if newObjectLayerFn() == nil {
return
return dsc
}
// Disable server-side replication on object prefixes which are excluded
// from versioning via the MinIO bucket versioning extension.
if !globalBucketVersioningSys.PrefixEnabled(bucket, object) {
return
return dsc
}
replStatus := mopts.ReplicationStatus()
if replStatus == replication.Replica && !mopts.isMetadataReplication() {
return
return dsc
}
if mopts.replicationRequest { // incoming replication request on target cluster
return
return dsc
}
cfg, err := getReplicationConfig(ctx, bucket)
if err != nil {
replLogOnceIf(ctx, err, bucket)
return
return dsc
}
if cfg == nil {
return
return dsc
}
opts := replication.ObjectOpts{
@ -347,16 +348,16 @@ func checkReplicateDelete(ctx context.Context, bucket string, dobj ObjectToDelet
rcfg, err := getReplicationConfig(ctx, bucket)
if err != nil || rcfg == nil {
replLogOnceIf(ctx, err, bucket)
return
return dsc
}
// If incoming request is a replication request, it does not need to be re-replicated.
if delOpts.ReplicationRequest {
return
return dsc
}
// Skip replication if this object's prefix is excluded from being
// versioned.
if !delOpts.Versioned {
return
return dsc
}
opts := replication.ObjectOpts{
Name: dobj.ObjectName,
@ -616,10 +617,10 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI
if dobj.VersionID == "" && rinfo.PrevReplicationStatus == replication.Completed && dobj.OpType != replication.ExistingObjectReplicationType {
rinfo.ReplicationStatus = rinfo.PrevReplicationStatus
return
return rinfo
}
if dobj.VersionID != "" && rinfo.VersionPurgeStatus == replication.VersionPurgeComplete {
return
return rinfo
}
if globalBucketTargetSys.isOffline(tgt.EndpointURL()) {
replLogOnceIf(ctx, fmt.Errorf("remote target is offline for bucket:%s arn:%s", dobj.Bucket, tgt.ARN), "replication-target-offline-delete-"+tgt.ARN)
@ -640,7 +641,7 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI
} else {
rinfo.VersionPurgeStatus = replication.VersionPurgeFailed
}
return
return rinfo
}
// early return if already replicated delete marker for existing object replication/ healing delete markers
if dobj.DeleteMarkerVersionID != "" {
@ -657,13 +658,13 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI
// delete marker already replicated
if dobj.VersionID == "" && rinfo.VersionPurgeStatus.Empty() {
rinfo.ReplicationStatus = replication.Completed
return
return rinfo
}
case isErrObjectNotFound(serr), isErrVersionNotFound(serr):
// version being purged is already not found on target.
if !rinfo.VersionPurgeStatus.Empty() {
rinfo.VersionPurgeStatus = replication.VersionPurgeComplete
return
return rinfo
}
case isErrReadQuorum(serr), isErrWriteQuorum(serr):
// destination has some quorum issues, perform removeObject() anyways
@ -677,7 +678,7 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI
if err != nil && !toi.ReplicationReady {
rinfo.ReplicationStatus = replication.Failed
rinfo.Err = err
return
return rinfo
}
}
}
@ -708,7 +709,7 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI
rinfo.VersionPurgeStatus = replication.VersionPurgeComplete
}
}
return
return rinfo
}
func getCopyObjMetadata(oi ObjectInfo, sc string) map[string]string {
@ -803,9 +804,7 @@ func putReplicationOpts(ctx context.Context, sc string, objInfo ObjectInfo) (put
} else {
cs, mp := getCRCMeta(objInfo, 0, nil)
// Set object checksum.
for k, v := range cs {
meta[k] = v
}
maps.Copy(meta, cs)
isMP = mp
if !objInfo.isMultipart() && cs[xhttp.AmzChecksumType] == xhttp.AmzChecksumTypeFullObject {
// For objects where checksum is full object, it will be the same.
@ -911,7 +910,7 @@ func putReplicationOpts(ctx context.Context, sc string, objInfo ObjectInfo) (put
}
putOpts.ServerSideEncryption = sseEnc
}
return
return putOpts, isMP, err
}
type replicationAction string
@ -969,9 +968,7 @@ func getReplicationAction(oi1 ObjectInfo, oi2 minio.ObjectInfo, opType replicati
t, _ := tags.ParseObjectTags(oi1.UserTags)
oi2Map := make(map[string]string)
for k, v := range oi2.UserTags {
oi2Map[k] = v
}
maps.Copy(oi2Map, oi2.UserTags)
if (oi2.UserTagCount > 0 && !reflect.DeepEqual(oi2Map, t.ToMap())) || (oi2.UserTagCount != len(t.ToMap())) {
return replicateMetadata
}
@ -1211,7 +1208,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
if ri.TargetReplicationStatus(tgt.ARN) == replication.Completed && !ri.ExistingObjResync.Empty() && !ri.ExistingObjResync.mustResyncTarget(tgt.ARN) {
rinfo.ReplicationStatus = replication.Completed
rinfo.ReplicationResynced = true
return
return rinfo
}
if globalBucketTargetSys.isOffline(tgt.EndpointURL()) {
@ -1223,7 +1220,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
versioned := globalBucketVersioningSys.PrefixEnabled(bucket, object)
@ -1247,7 +1244,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
})
replLogOnceIf(ctx, fmt.Errorf("unable to read source object %s/%s(%s): %w", bucket, object, objInfo.VersionID, err), object+":"+objInfo.VersionID)
}
return
return rinfo
}
defer gr.Close()
@ -1271,7 +1268,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
}
@ -1310,7 +1307,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
var headerSize int
@ -1347,7 +1344,7 @@ func (ri ReplicateObjectInfo) replicateObject(ctx context.Context, objectAPI Obj
globalBucketTargetSys.markOffline(tgt.EndpointURL())
}
}
return
return rinfo
}
// replicateAll replicates metadata for specified version of the object to destination bucket
@ -1383,7 +1380,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
versioned := globalBucketVersioningSys.PrefixEnabled(bucket, object)
@ -1408,7 +1405,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
})
replLogIf(ctx, fmt.Errorf("unable to replicate to target %s for %s/%s(%s): %w", tgt.EndpointURL(), bucket, object, objInfo.VersionID, err))
}
return
return rinfo
}
defer gr.Close()
@ -1421,7 +1418,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
if objInfo.TargetReplicationStatus(tgt.ARN) == replication.Completed && !ri.ExistingObjResync.Empty() && !ri.ExistingObjResync.mustResyncTarget(tgt.ARN) {
rinfo.ReplicationStatus = replication.Completed
rinfo.ReplicationResynced = true
return
return rinfo
}
size, err := objInfo.GetActualSize()
@ -1434,7 +1431,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
// Set the encrypted size for SSE-C objects
@ -1497,7 +1494,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
rinfo.ReplicationAction = rAction
rinfo.ReplicationStatus = replication.Completed
}
return
return rinfo
}
} else {
// SSEC objects will refuse HeadObject without the decryption key.
@ -1531,7 +1528,7 @@ func (ri ReplicateObjectInfo) replicateAll(ctx context.Context, objectAPI Object
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
}
applyAction:
@ -1597,7 +1594,7 @@ applyAction:
UserAgent: "Internal: [Replication]",
Host: globalLocalNodeName,
})
return
return rinfo
}
var headerSize int
for k, v := range putOpts.Header() {
@ -1634,7 +1631,7 @@ applyAction:
}
}
}
return
return rinfo
}
func replicateObjectWithMultipart(ctx context.Context, c *minio.Core, bucket, object string, r io.Reader, objInfo ObjectInfo, opts minio.PutObjectOptions) (err error) {
@ -1770,9 +1767,7 @@ func filterReplicationStatusMetadata(metadata map[string]string) map[string]stri
}
if !copied {
dst = make(map[string]string, len(metadata))
for k, v := range metadata {
dst[k] = v
}
maps.Copy(dst, metadata)
copied = true
}
delete(dst, key)
@ -2682,7 +2677,7 @@ func (c replicationConfig) Replicate(opts replication.ObjectOpts) bool {
// Resync returns true if replication reset is requested
func (c replicationConfig) Resync(ctx context.Context, oi ObjectInfo, dsc ReplicateDecision, tgtStatuses map[string]replication.StatusType) (r ResyncDecision) {
if c.Empty() {
return
return r
}
// Now overlay existing object replication choices for target
@ -2698,7 +2693,7 @@ func (c replicationConfig) Resync(ctx context.Context, oi ObjectInfo, dsc Replic
tgtArns := c.Config.FilterTargetArns(opts)
// indicates no matching target with Existing object replication enabled.
if len(tgtArns) == 0 {
return
return r
}
for _, t := range tgtArns {
opts.TargetArn = t
@ -2724,7 +2719,7 @@ func (c replicationConfig) resync(oi ObjectInfo, dsc ReplicateDecision, tgtStatu
targets: make(map[string]ResyncTargetDecision, len(dsc.targetsMap)),
}
if c.remotes == nil {
return
return r
}
for _, tgt := range c.remotes.Targets {
d, ok := dsc.targetsMap[tgt.Arn]
@ -2736,7 +2731,7 @@ func (c replicationConfig) resync(oi ObjectInfo, dsc ReplicateDecision, tgtStatu
}
r.targets[d.Arn] = resyncTarget(oi, tgt.Arn, tgt.ResetID, tgt.ResetBeforeDate, tgtStatuses[tgt.Arn])
}
return
return r
}
func targetResetHeader(arn string) string {
@ -2755,28 +2750,28 @@ func resyncTarget(oi ObjectInfo, arn string, resetID string, resetBeforeDate tim
if !ok { // existing object replication is enabled and object version is unreplicated so far.
if resetID != "" && oi.ModTime.Before(resetBeforeDate) { // trigger replication if `mc replicate reset` requested
rd.Replicate = true
return
return rd
}
// For existing object reset - this condition is needed
rd.Replicate = tgtStatus == ""
return
return rd
}
if resetID == "" || resetBeforeDate.Equal(timeSentinel) { // no reset in progress
return
return rd
}
// if already replicated, return true if a new reset was requested.
splits := strings.SplitN(rs, ";", 2)
if len(splits) != 2 {
return
return rd
}
newReset := splits[1] != resetID
if !newReset && tgtStatus == replication.Completed {
// already replicated and no reset requested
return
return rd
}
rd.Replicate = newReset && oi.ModTime.Before(resetBeforeDate)
return
return rd
}
const resyncTimeInterval = time.Minute * 1
@ -2954,7 +2949,7 @@ func (s *replicationResyncer) resyncBucket(ctx context.Context, objectAPI Object
}()
var wg sync.WaitGroup
for i := 0; i < resyncParallelRoutines; i++ {
for i := range resyncParallelRoutines {
wg.Add(1)
workers[i] = make(chan ReplicateObjectInfo, 100)
i := i
@ -3063,7 +3058,7 @@ func (s *replicationResyncer) resyncBucket(ctx context.Context, objectAPI Object
workers[h%uint64(resyncParallelRoutines)] <- roi
}
}
for i := 0; i < resyncParallelRoutines; i++ {
for i := range resyncParallelRoutines {
xioutil.SafeClose(workers[i])
}
wg.Wait()
@ -3193,11 +3188,9 @@ func (p *ReplicationPool) startResyncRoutine(ctx context.Context, buckets []stri
<-ctx.Done()
return
}
duration := time.Duration(r.Float64() * float64(time.Minute))
if duration < time.Second {
duration := max(time.Duration(r.Float64()*float64(time.Minute)),
// Make sure to sleep at least a second to avoid high CPU ticks.
duration = time.Second
}
time.Second)
time.Sleep(duration)
}
}
@ -3429,12 +3422,12 @@ func queueReplicationHeal(ctx context.Context, bucket string, oi ObjectInfo, rcf
roi = getHealReplicateObjectInfo(oi, rcfg)
roi.RetryCount = uint32(retryCount)
if !roi.Dsc.ReplicateAny() {
return
return roi
}
// early return if replication already done, otherwise we need to determine if this
// version is an existing object that needs healing.
if oi.ReplicationStatus == replication.Completed && oi.VersionPurgeStatus.Empty() && !roi.ExistingObjResync.mustResync() {
return
return roi
}
if roi.DeleteMarker || !roi.VersionPurgeStatus.Empty() {
@ -3464,14 +3457,14 @@ func queueReplicationHeal(ctx context.Context, bucket string, oi ObjectInfo, rcf
roi.ReplicationStatus == replication.Failed ||
roi.VersionPurgeStatus == replication.VersionPurgeFailed || roi.VersionPurgeStatus == replication.VersionPurgePending {
globalReplicationPool.Get().queueReplicaDeleteTask(dv)
return
return roi
}
// if replication status is Complete on DeleteMarker and existing object resync required
if roi.ExistingObjResync.mustResync() && (roi.ReplicationStatus == replication.Completed || roi.ReplicationStatus.Empty()) {
queueReplicateDeletesWrapper(dv, roi.ExistingObjResync)
return
return roi
}
return
return roi
}
if roi.ExistingObjResync.mustResync() {
roi.OpType = replication.ExistingObjectReplicationType
@ -3480,13 +3473,13 @@ func queueReplicationHeal(ctx context.Context, bucket string, oi ObjectInfo, rcf
case replication.Pending, replication.Failed:
roi.EventType = ReplicateHeal
globalReplicationPool.Get().queueReplicaTask(roi)
return
return roi
}
if roi.ExistingObjResync.mustResync() {
roi.EventType = ReplicateExisting
globalReplicationPool.Get().queueReplicaTask(roi)
}
return
return roi
}
const (
@ -3797,14 +3790,13 @@ func getCRCMeta(oi ObjectInfo, partNum int, h http.Header) (cs map[string]string
meta := make(map[string]string)
cs, isMP = oi.decryptChecksums(partNum, h)
for k, v := range cs {
cksum := hash.NewChecksumString(k, v)
if cksum == nil {
if k == xhttp.AmzChecksumType {
continue
}
if cksum.Valid() {
meta[cksum.Type.Key()] = v
meta[xhttp.AmzChecksumType] = cs[xhttp.AmzChecksumType]
meta[xhttp.AmzChecksumAlgo] = cksum.Type.String()
cktype := hash.ChecksumStringToType(k)
if cktype.IsSet() {
meta[cktype.Key()] = v
meta[xhttp.AmzChecksumAlgo] = cktype.String()
}
}
return meta, isMP

View File

@ -19,6 +19,7 @@ package cmd
import (
"fmt"
"maps"
"math"
"sync/atomic"
"time"
@ -37,7 +38,7 @@ type ReplicationLatency struct {
// Merge two replication latency into a new one
func (rl ReplicationLatency) merge(other ReplicationLatency) (newReplLatency ReplicationLatency) {
newReplLatency.UploadHistogram = rl.UploadHistogram.Merge(other.UploadHistogram)
return
return newReplLatency
}
// Get upload latency of each object size range
@ -48,7 +49,7 @@ func (rl ReplicationLatency) getUploadLatency() (ret map[string]uint64) {
// Convert nanoseconds to milliseconds
ret[sizeTagToString(k)] = uint64(v.avg() / time.Millisecond)
}
return
return ret
}
// Update replication upload latency with a new value
@ -63,7 +64,7 @@ type ReplicationLastMinute struct {
func (rl ReplicationLastMinute) merge(other ReplicationLastMinute) (nl ReplicationLastMinute) {
nl = ReplicationLastMinute{rl.LastMinute.merge(other.LastMinute)}
return
return nl
}
func (rl *ReplicationLastMinute) addsize(n int64) {
@ -221,9 +222,7 @@ func (brs BucketReplicationStats) Clone() (c BucketReplicationStats) {
}
if s.Failed.ErrCounts == nil {
s.Failed.ErrCounts = make(map[string]int)
for k, v := range st.Failed.ErrCounts {
s.Failed.ErrCounts[k] = v
}
maps.Copy(s.Failed.ErrCounts, st.Failed.ErrCounts)
}
c.Stats[arn] = &s
}

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)
@ -617,19 +617,17 @@ func (z *BucketReplicationStats) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Stats == nil {
z.Stats = make(map[string]*BucketReplicationStat, zb0002)
} else if len(z.Stats) > 0 {
for key := range z.Stats {
delete(z.Stats, key)
}
clear(z.Stats)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 *BucketReplicationStat
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Stats")
return
}
var za0002 *BucketReplicationStat
if dc.IsNil() {
err = dc.ReadNil()
if err != nil {
@ -943,14 +941,12 @@ func (z *BucketReplicationStats) UnmarshalMsg(bts []byte) (o []byte, err error)
if z.Stats == nil {
z.Stats = make(map[string]*BucketReplicationStat, zb0002)
} else if len(z.Stats) > 0 {
for key := range z.Stats {
delete(z.Stats, key)
}
clear(z.Stats)
}
for zb0002 > 0 {
var za0001 string
var za0002 *BucketReplicationStat
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Stats")
@ -1402,19 +1398,17 @@ func (z *BucketStatsMap) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Stats == nil {
z.Stats = make(map[string]BucketStats, zb0002)
} else if len(z.Stats) > 0 {
for key := range z.Stats {
delete(z.Stats, key)
}
clear(z.Stats)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 BucketStats
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Stats")
return
}
var za0002 BucketStats
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Stats", za0001)
@ -1526,14 +1520,12 @@ func (z *BucketStatsMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Stats == nil {
z.Stats = make(map[string]BucketStats, zb0002)
} else if len(z.Stats) > 0 {
for key := range z.Stats {
delete(z.Stats, key)
}
clear(z.Stats)
}
for zb0002 > 0 {
var za0001 string
var za0002 BucketStats
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Stats")

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -20,6 +20,7 @@ package cmd
import (
"context"
"errors"
"maps"
"net/url"
"sync"
"time"
@ -236,9 +237,7 @@ func (sys *BucketTargetSys) healthStats() map[string]epHealth {
sys.hMutex.RLock()
defer sys.hMutex.RUnlock()
m := make(map[string]epHealth, len(sys.hc))
for k, v := range sys.hc {
m[k] = v
}
maps.Copy(m, sys.hc)
return m
}
@ -286,7 +285,7 @@ func (sys *BucketTargetSys) ListTargets(ctx context.Context, bucket, arnType str
}
}
}
return
return targets
}
// ListBucketTargets - gets list of bucket targets for this bucket.
@ -669,7 +668,7 @@ func (sys *BucketTargetSys) getRemoteTargetClient(tcfg *madmin.BucketTarget) (*T
// getRemoteARN gets existing ARN for an endpoint or generates a new one.
func (sys *BucketTargetSys) getRemoteARN(bucket string, target *madmin.BucketTarget, deplID string) (arn string, exists bool) {
if target == nil {
return
return arn, exists
}
sys.RLock()
defer sys.RUnlock()
@ -683,7 +682,7 @@ func (sys *BucketTargetSys) getRemoteARN(bucket string, target *madmin.BucketTar
}
}
if !target.Type.IsValid() {
return
return arn, exists
}
return generateARN(target, deplID), false
}

View File

@ -57,11 +57,9 @@ func initCallhome(ctx context.Context, objAPI ObjectLayer) {
// callhome running on a different node.
// sleep for some time and try again.
duration := time.Duration(r.Float64() * float64(globalCallhomeConfig.FrequencyDur()))
if duration < time.Second {
duration := max(time.Duration(r.Float64()*float64(globalCallhomeConfig.FrequencyDur())),
// Make sure to sleep at least a second to avoid high CPU ticks.
duration = time.Second
}
time.Second)
time.Sleep(duration)
}
}()

View File

@ -105,7 +105,7 @@ func init() {
gob.Register(madmin.TimeInfo{})
gob.Register(madmin.XFSErrorConfigs{})
gob.Register(map[string]string{})
gob.Register(map[string]interface{}{})
gob.Register(map[string]any{})
// All minio-go and madmin-go API operations shall be performed only once,
// another way to look at this is we are turning off retries.
@ -258,7 +258,7 @@ func initConsoleServer() (*consoleapi.Server, error) {
if !serverDebugLog {
// Disable console logging if server debug log is not enabled
noLog := func(string, ...interface{}) {}
noLog := func(string, ...any) {}
consoleapi.LogInfo = noLog
consoleapi.LogError = noLog
@ -761,7 +761,7 @@ func serverHandleEnvVars() {
domains := env.Get(config.EnvDomain, "")
if len(domains) != 0 {
for _, domainName := range strings.Split(domains, config.ValueSeparator) {
for domainName := range strings.SplitSeq(domains, config.ValueSeparator) {
if _, ok := dns2.IsDomainName(domainName); !ok {
logger.Fatal(config.ErrInvalidDomainValue(nil).Msgf("Unknown value `%s`", domainName),
"Invalid MINIO_DOMAIN value in environment variable")
@ -1059,6 +1059,6 @@ func (a bgCtx) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (a bgCtx) Value(key interface{}) interface{} {
func (a bgCtx) Value(key any) any {
return a.parent.Value(key)
}

View File

@ -43,7 +43,6 @@ func Test_readFromSecret(t *testing.T) {
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
tmpfile, err := os.CreateTemp(t.TempDir(), "testfile")
if err != nil {
@ -155,7 +154,6 @@ MINIO_ROOT_PASSWORD=minio123`,
},
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
tmpfile, err := os.CreateTemp(t.TempDir(), "testfile")
if err != nil {

View File

@ -21,6 +21,7 @@ import (
"context"
"errors"
"fmt"
"maps"
"strings"
"sync"
@ -78,12 +79,8 @@ func initHelp() {
config.BatchSubSys: batch.DefaultKVS,
config.BrowserSubSys: browser.DefaultKVS,
}
for k, v := range notify.DefaultNotificationKVS {
kvs[k] = v
}
for k, v := range lambda.DefaultLambdaKVS {
kvs[k] = v
}
maps.Copy(kvs, notify.DefaultNotificationKVS)
maps.Copy(kvs, lambda.DefaultLambdaKVS)
if globalIsErasure {
kvs[config.StorageClassSubSys] = storageclass.DefaultKVS
kvs[config.HealSubSys] = heal.DefaultKVS
@ -355,7 +352,9 @@ func validateSubSysConfig(ctx context.Context, s config.Config, subSys string, o
}
case config.IdentityOpenIDSubSys:
if _, err := openid.LookupConfig(s,
NewHTTPTransport(), xhttp.DrainBody, globalSite.Region()); err != nil {
xhttp.WithUserAgent(NewHTTPTransport(), func() string {
return getUserAgent(getMinioMode())
}), xhttp.DrainBody, globalSite.Region()); err != nil {
return err
}
case config.IdentityLDAPSubSys:

View File

@ -38,12 +38,12 @@ import (
)
// Save config file to corresponding backend
func Save(configFile string, data interface{}) error {
func Save(configFile string, data any) error {
return quick.SaveConfig(data, configFile, globalEtcdClient)
}
// Load config from backend
func Load(configFile string, data interface{}) (quick.Config, error) {
func Load(configFile string, data any) (quick.Config, error) {
return quick.LoadConfig(configFile, globalEtcdClient, data)
}

View File

@ -129,7 +129,7 @@ func saveServerConfigHistory(ctx context.Context, objAPI ObjectLayer, kv []byte)
return saveConfig(ctx, objAPI, historyFile, kv)
}
func saveServerConfig(ctx context.Context, objAPI ObjectLayer, cfg interface{}) error {
func saveServerConfig(ctx context.Context, objAPI ObjectLayer, cfg any) error {
data, err := json.Marshal(cfg)
if err != nil {
return err

View File

@ -101,7 +101,7 @@ func (sys *HTTPConsoleLoggerSys) Subscribe(subCh chan log.Info, doneCh <-chan st
lastN = make([]log.Info, last)
sys.RLock()
sys.logBuf.Do(func(p interface{}) {
sys.logBuf.Do(func(p any) {
if p != nil {
lg, ok := p.(log.Info)
if ok && lg.SendLog(node, logKind) {
@ -155,7 +155,7 @@ func (sys *HTTPConsoleLoggerSys) Stats() types.TargetStats {
// Content returns the console stdout log
func (sys *HTTPConsoleLoggerSys) Content() (logs []log.Entry) {
sys.RLock()
sys.logBuf.Do(func(p interface{}) {
sys.logBuf.Do(func(p any) {
if p != nil {
lg, ok := p.(log.Info)
if ok {
@ -167,7 +167,7 @@ func (sys *HTTPConsoleLoggerSys) Content() (logs []log.Entry) {
})
sys.RUnlock()
return
return logs
}
// Cancel - cancels the target
@ -181,7 +181,7 @@ func (sys *HTTPConsoleLoggerSys) Type() types.TargetType {
// Send log message 'e' to console and publish to console
// log pubsub system
func (sys *HTTPConsoleLoggerSys) Send(ctx context.Context, entry interface{}) error {
func (sys *HTTPConsoleLoggerSys) Send(ctx context.Context, entry any) error {
var lg log.Info
switch e := entry.(type) {
case log.Entry:

View File

@ -106,16 +106,14 @@ func (p *scannerMetrics) log(s scannerMetric, paths ...string) func(custom map[s
// time n scanner actions.
// Use for s < scannerMetricLastRealtime
func (p *scannerMetrics) timeN(s scannerMetric) func(n int) func() {
func (p *scannerMetrics) timeN(s scannerMetric) func(n int) {
startTime := time.Now()
return func(n int) func() {
return func() {
duration := time.Since(startTime)
return func(n int) {
duration := time.Since(startTime)
atomic.AddUint64(&p.operations[s], uint64(n))
if s < scannerMetricLastRealtime {
p.latency[s].add(duration)
}
atomic.AddUint64(&p.operations[s], uint64(n))
if s < scannerMetricLastRealtime {
p.latency[s].add(duration)
}
}
}
@ -198,7 +196,7 @@ func (p *scannerMetrics) currentPathUpdater(disk, initial string) (update func(p
func (p *scannerMetrics) getCurrentPaths() []string {
var res []string
prefix := globalLocalNodeName + "/"
p.currentPaths.Range(func(key, value interface{}) bool {
p.currentPaths.Range(func(key, value any) bool {
// We are a bit paranoid, but better miss an entry than crash.
name, ok := key.(string)
if !ok {
@ -221,7 +219,7 @@ func (p *scannerMetrics) getCurrentPaths() []string {
// (since this is concurrent it may not be 100% reliable)
func (p *scannerMetrics) activeDrives() int {
var i int
p.currentPaths.Range(func(k, v interface{}) bool {
p.currentPaths.Range(func(k, v any) bool {
i++
return true
})
@ -299,7 +297,7 @@ func (p *scannerMetrics) report() madmin.ScannerMetrics {
m.CollectedAt = time.Now()
m.ActivePaths = p.getCurrentPaths()
m.LifeTimeOps = make(map[string]uint64, scannerMetricLast)
for i := scannerMetric(0); i < scannerMetricLast; i++ {
for i := range scannerMetricLast {
if n := atomic.LoadUint64(&p.operations[i]); n > 0 {
m.LifeTimeOps[i.String()] = n
}
@ -309,7 +307,7 @@ func (p *scannerMetrics) report() madmin.ScannerMetrics {
}
m.LastMinute.Actions = make(map[string]madmin.TimedAction, scannerMetricLastRealtime)
for i := scannerMetric(0); i < scannerMetricLastRealtime; i++ {
for i := range scannerMetricLastRealtime {
lm := p.lastMinute(i)
if lm.N > 0 {
m.LastMinute.Actions[i.String()] = lm.asTimedAction()

View File

@ -78,11 +78,9 @@ func initDataScanner(ctx context.Context, objAPI ObjectLayer) {
// Run the data scanner in a loop
for {
runDataScanner(ctx, objAPI)
duration := time.Duration(r.Float64() * float64(scannerCycle.Load()))
if duration < time.Second {
duration := max(time.Duration(r.Float64()*float64(scannerCycle.Load())),
// Make sure to sleep at least a second to avoid high CPU ticks.
duration = time.Second
}
time.Second)
time.Sleep(duration)
}
}()

View File

@ -127,7 +127,7 @@ func TestApplyNewerNoncurrentVersionsLimit(t *testing.T) {
v2 uuid-2 modTime -3m
v1 uuid-1 modTime -4m
*/
for i := 0; i < 5; i++ {
for i := range 5 {
fivs[i] = FileInfo{
Volume: bucket,
Name: obj,

View File

@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"math/rand"
"net/http"
"path"
@ -99,9 +100,7 @@ func (ats *allTierStats) clone() *allTierStats {
}
dst := *ats
dst.Tiers = make(map[string]tierStats, len(ats.Tiers))
for tier, st := range ats.Tiers {
dst.Tiers[tier] = st
}
maps.Copy(dst.Tiers, ats.Tiers)
return &dst
}
@ -347,9 +346,7 @@ func (e dataUsageEntry) clone() dataUsageEntry {
// We operate on a copy from the receiver.
if e.Children != nil {
ch := make(dataUsageHashMap, len(e.Children))
for k, v := range e.Children {
ch[k] = v
}
maps.Copy(ch, e.Children)
e.Children = ch
}
@ -1224,11 +1221,11 @@ func (z *dataUsageHashMap) DecodeMsg(dc *msgp.Reader) (err error) {
zb0002, err = dc.ReadArrayHeader()
if err != nil {
err = msgp.WrapError(err)
return
return err
}
if zb0002 == 0 {
*z = nil
return
return err
}
*z = make(dataUsageHashMap, zb0002)
for i := uint32(0); i < zb0002; i++ {
@ -1237,12 +1234,12 @@ func (z *dataUsageHashMap) DecodeMsg(dc *msgp.Reader) (err error) {
zb0003, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err)
return
return err
}
(*z)[zb0003] = struct{}{}
}
}
return
return err
}
// EncodeMsg implements msgp.Encodable
@ -1250,16 +1247,16 @@ func (z dataUsageHashMap) EncodeMsg(en *msgp.Writer) (err error) {
err = en.WriteArrayHeader(uint32(len(z)))
if err != nil {
err = msgp.WrapError(err)
return
return err
}
for zb0004 := range z {
err = en.WriteString(zb0004)
if err != nil {
err = msgp.WrapError(err, zb0004)
return
return err
}
}
return
return err
}
// MarshalMsg implements msgp.Marshaler
@ -1269,7 +1266,7 @@ func (z dataUsageHashMap) MarshalMsg(b []byte) (o []byte, err error) {
for zb0004 := range z {
o = msgp.AppendString(o, zb0004)
}
return
return o, err
}
// UnmarshalMsg implements msgp.Unmarshaler
@ -1278,7 +1275,7 @@ func (z *dataUsageHashMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
return o, err
}
if zb0002 == 0 {
*z = nil
@ -1291,13 +1288,13 @@ func (z *dataUsageHashMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
zb0003, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
return o, err
}
(*z)[zb0003] = struct{}{}
}
}
o = bts
return
return o, err
}
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
@ -1306,7 +1303,7 @@ func (z dataUsageHashMap) Msgsize() (s int) {
for zb0004 := range z {
s += msgp.StringPrefixSize + len(zb0004)
}
return
return s
}
//msgp:encode ignore currentScannerCycle

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"time"
@ -36,19 +36,17 @@ func (z *allTierStats) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Tiers == nil {
z.Tiers = make(map[string]tierStats, zb0002)
} else if len(z.Tiers) > 0 {
for key := range z.Tiers {
delete(z.Tiers, key)
}
clear(z.Tiers)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 tierStats
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Tiers")
return
}
var za0002 tierStats
var zb0003 uint32
zb0003, err = dc.ReadMapHeader()
if err != nil {
@ -207,14 +205,12 @@ func (z *allTierStats) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Tiers == nil {
z.Tiers = make(map[string]tierStats, zb0002)
} else if len(z.Tiers) > 0 {
for key := range z.Tiers {
delete(z.Tiers, key)
}
clear(z.Tiers)
}
for zb0002 > 0 {
var za0001 string
var za0002 tierStats
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Tiers")
@ -415,19 +411,17 @@ func (z *dataUsageCache) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntry, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntry
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntry
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -543,14 +537,12 @@ func (z *dataUsageCache) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntry, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntry
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -799,19 +791,17 @@ func (z *dataUsageCacheV2) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV2, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV2
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV2
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -864,14 +854,12 @@ func (z *dataUsageCacheV2) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV2, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV2
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -942,19 +930,17 @@ func (z *dataUsageCacheV3) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV3, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV3
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV3
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -1007,14 +993,12 @@ func (z *dataUsageCacheV3) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV3, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV3
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -1085,19 +1069,17 @@ func (z *dataUsageCacheV4) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV4, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV4
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV4
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -1150,14 +1132,12 @@ func (z *dataUsageCacheV4) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV4, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV4
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -1228,19 +1208,17 @@ func (z *dataUsageCacheV5) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV5, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV5
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV5
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -1293,14 +1271,12 @@ func (z *dataUsageCacheV5) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV5, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV5
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -1371,19 +1347,17 @@ func (z *dataUsageCacheV6) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV6, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV6
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV6
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -1436,14 +1410,12 @@ func (z *dataUsageCacheV6) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV6, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV6
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -1514,19 +1486,17 @@ func (z *dataUsageCacheV7) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV7, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 dataUsageEntryV7
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Cache")
return
}
var za0002 dataUsageEntryV7
err = za0002.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Cache", za0001)
@ -1579,14 +1549,12 @@ func (z *dataUsageCacheV7) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.Cache == nil {
z.Cache = make(map[string]dataUsageEntryV7, zb0002)
} else if len(z.Cache) > 0 {
for key := range z.Cache {
delete(z.Cache, key)
}
clear(z.Cache)
}
for zb0002 > 0 {
var za0001 string
var za0002 dataUsageEntryV7
zb0002--
var za0001 string
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Cache")
@ -1745,19 +1713,17 @@ func (z *dataUsageEntry) DecodeMsg(dc *msgp.Reader) (err error) {
if z.AllTierStats.Tiers == nil {
z.AllTierStats.Tiers = make(map[string]tierStats, zb0005)
} else if len(z.AllTierStats.Tiers) > 0 {
for key := range z.AllTierStats.Tiers {
delete(z.AllTierStats.Tiers, key)
}
clear(z.AllTierStats.Tiers)
}
for zb0005 > 0 {
zb0005--
var za0003 string
var za0004 tierStats
za0003, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "AllTierStats", "Tiers")
return
}
var za0004 tierStats
var zb0006 uint32
zb0006, err = dc.ReadMapHeader()
if err != nil {
@ -2211,14 +2177,12 @@ func (z *dataUsageEntry) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.AllTierStats.Tiers == nil {
z.AllTierStats.Tiers = make(map[string]tierStats, zb0005)
} else if len(z.AllTierStats.Tiers) > 0 {
for key := range z.AllTierStats.Tiers {
delete(z.AllTierStats.Tiers, key)
}
clear(z.AllTierStats.Tiers)
}
for zb0005 > 0 {
var za0003 string
var za0004 tierStats
zb0005--
var za0003 string
za0003, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "AllTierStats", "Tiers")
@ -2984,19 +2948,17 @@ func (z *dataUsageEntryV7) DecodeMsg(dc *msgp.Reader) (err error) {
if z.AllTierStats.Tiers == nil {
z.AllTierStats.Tiers = make(map[string]tierStats, zb0005)
} else if len(z.AllTierStats.Tiers) > 0 {
for key := range z.AllTierStats.Tiers {
delete(z.AllTierStats.Tiers, key)
}
clear(z.AllTierStats.Tiers)
}
for zb0005 > 0 {
zb0005--
var za0003 string
var za0004 tierStats
za0003, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "AllTierStats", "Tiers")
return
}
var za0004 tierStats
var zb0006 uint32
zb0006, err = dc.ReadMapHeader()
if err != nil {
@ -3192,14 +3154,12 @@ func (z *dataUsageEntryV7) UnmarshalMsg(bts []byte) (o []byte, err error) {
if z.AllTierStats.Tiers == nil {
z.AllTierStats.Tiers = make(map[string]tierStats, zb0005)
} else if len(z.AllTierStats.Tiers) > 0 {
for key := range z.AllTierStats.Tiers {
delete(z.AllTierStats.Tiers, key)
}
clear(z.AllTierStats.Tiers)
}
for zb0005 > 0 {
var za0003 string
var za0004 tierStats
zb0005--
var za0003 string
za0003, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "AllTierStats", "Tiers")

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

View File

@ -56,13 +56,13 @@ func TestDataUsageUpdate(t *testing.T) {
var s os.FileInfo
s, err = os.Stat(item.Path)
if err != nil {
return
return sizeS, err
}
sizeS.totalSize = s.Size()
sizeS.versions++
return sizeS, nil
}
return
return sizeS, err
}
xls := xlStorage{drivePath: base, diskInfoCache: cachevalue.New[DiskInfo]()}
xls.diskInfoCache.InitOnce(time.Second, cachevalue.Opts{}, func(ctx context.Context) (DiskInfo, error) {
@ -179,7 +179,7 @@ func TestDataUsageUpdate(t *testing.T) {
t.Fatal(err)
}
// Changed dir must be picked up in this many cycles.
for i := 0; i < dataUsageUpdateDirCycles; i++ {
for range dataUsageUpdateDirCycles {
got, err = scanDataFolder(t.Context(), nil, &xls, got, getSize, 0, weSleep)
got.Info.NextCycle++
if err != nil {
@ -279,13 +279,13 @@ func TestDataUsageUpdatePrefix(t *testing.T) {
var s os.FileInfo
s, err = os.Stat(item.Path)
if err != nil {
return
return sizeS, err
}
sizeS.totalSize = s.Size()
sizeS.versions++
return
return sizeS, err
}
return
return sizeS, err
}
weSleep := func() bool { return false }
@ -428,7 +428,7 @@ func TestDataUsageUpdatePrefix(t *testing.T) {
t.Fatal(err)
}
// Changed dir must be picked up in this many cycles.
for i := 0; i < dataUsageUpdateDirCycles; i++ {
for range dataUsageUpdateDirCycles {
got, err = scanDataFolder(t.Context(), nil, &xls, got, getSize, 0, weSleep)
got.Info.NextCycle++
if err != nil {
@ -526,13 +526,13 @@ func createUsageTestFiles(t *testing.T, base, bucket string, files []usageTestFi
// generateUsageTestFiles create nFolders * nFiles files of size bytes each.
func generateUsageTestFiles(t *testing.T, base, bucket string, nFolders, nFiles, size int) {
pl := make([]byte, size)
for i := 0; i < nFolders; i++ {
for i := range nFolders {
name := filepath.Join(base, bucket, fmt.Sprint(i), "0.txt")
err := os.MkdirAll(filepath.Dir(name), os.ModePerm)
if err != nil {
t.Fatal(err)
}
for j := 0; j < nFiles; j++ {
for j := range nFiles {
name := filepath.Join(base, bucket, fmt.Sprint(i), fmt.Sprint(j)+".txt")
err = os.WriteFile(name, pl, os.ModePerm)
if err != nil {
@ -569,13 +569,13 @@ func TestDataUsageCacheSerialize(t *testing.T) {
var s os.FileInfo
s, err = os.Stat(item.Path)
if err != nil {
return
return sizeS, err
}
sizeS.versions++
sizeS.totalSize = s.Size()
return
return sizeS, err
}
return
return sizeS, err
}
xls := xlStorage{drivePath: base, diskInfoCache: cachevalue.New[DiskInfo]()}
xls.diskInfoCache.InitOnce(time.Second, cachevalue.Opts{}, func(ctx context.Context) (DiskInfo, error) {
@ -618,7 +618,7 @@ func TestDataUsageCacheSerialize(t *testing.T) {
}
// equalAsJSON returns whether the values are equal when encoded as JSON.
func equalAsJSON(a, b interface{}) bool {
func equalAsJSON(a, b any) bool {
aj, err := json.Marshal(a)
if err != nil {
panic(err)

View File

@ -87,7 +87,7 @@ func (d *DummyDataGen) Read(b []byte) (n int, err error) {
}
err = io.EOF
}
return
return n, err
}
func (d *DummyDataGen) Seek(offset int64, whence int) (int64, error) {

View File

@ -129,12 +129,9 @@ func (dt *dynamicTimeout) adjust(entries [dynamicTimeoutLogSize]time.Duration) {
if failPct > dynamicTimeoutIncreaseThresholdPct {
// We are hitting the timeout too often, so increase the timeout by 25%
timeout := atomic.LoadInt64(&dt.timeout) * 125 / 100
// Set upper cap.
if timeout > int64(maxDynamicTimeout) {
timeout = int64(maxDynamicTimeout)
}
timeout := min(
// Set upper cap.
atomic.LoadInt64(&dt.timeout)*125/100, int64(maxDynamicTimeout))
// Safety, shouldn't happen
if timeout < dt.minimum {
timeout = dt.minimum

View File

@ -30,7 +30,7 @@ func TestDynamicTimeoutSingleIncrease(t *testing.T) {
initial := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogFailure()
}
@ -46,13 +46,13 @@ func TestDynamicTimeoutDualIncrease(t *testing.T) {
initial := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogFailure()
}
adjusted := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogFailure()
}
@ -68,7 +68,7 @@ func TestDynamicTimeoutSingleDecrease(t *testing.T) {
initial := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogSuccess(20 * time.Second)
}
@ -84,13 +84,13 @@ func TestDynamicTimeoutDualDecrease(t *testing.T) {
initial := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogSuccess(20 * time.Second)
}
adjusted := timeout.Timeout()
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
timeout.LogSuccess(20 * time.Second)
}
@ -107,8 +107,8 @@ func TestDynamicTimeoutManyDecreases(t *testing.T) {
initial := timeout.Timeout()
const successTimeout = 20 * time.Second
for l := 0; l < 100; l++ {
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range 100 {
for range dynamicTimeoutLogSize {
timeout.LogSuccess(successTimeout)
}
}
@ -129,8 +129,8 @@ func TestDynamicTimeoutConcurrent(t *testing.T) {
rng := rand.New(rand.NewSource(int64(i)))
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
for j := 0; j < 100; j++ {
for range 100 {
for range 100 {
timeout.LogSuccess(time.Duration(float64(time.Second) * rng.Float64()))
}
to := timeout.Timeout()
@ -150,8 +150,8 @@ func TestDynamicTimeoutHitMinimum(t *testing.T) {
initial := timeout.Timeout()
const successTimeout = 20 * time.Second
for l := 0; l < 100; l++ {
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range 100 {
for range dynamicTimeoutLogSize {
timeout.LogSuccess(successTimeout)
}
}
@ -166,13 +166,9 @@ func TestDynamicTimeoutHitMinimum(t *testing.T) {
func testDynamicTimeoutAdjust(t *testing.T, timeout *dynamicTimeout, f func() float64) {
const successTimeout = 20 * time.Second
for i := 0; i < dynamicTimeoutLogSize; i++ {
for range dynamicTimeoutLogSize {
rnd := f()
duration := time.Duration(float64(successTimeout) * rnd)
if duration < 100*time.Millisecond {
duration = 100 * time.Millisecond
}
duration := max(time.Duration(float64(successTimeout)*rnd), 100*time.Millisecond)
if duration >= time.Minute {
timeout.LogFailure()
} else {
@ -188,7 +184,7 @@ func TestDynamicTimeoutAdjustExponential(t *testing.T) {
initial := timeout.Timeout()
for try := 0; try < 10; try++ {
for range 10 {
testDynamicTimeoutAdjust(t, timeout, rand.ExpFloat64)
}
@ -205,7 +201,7 @@ func TestDynamicTimeoutAdjustNormalized(t *testing.T) {
initial := timeout.Timeout()
for try := 0; try < 10; try++ {
for range 10 {
testDynamicTimeoutAdjust(t, timeout, func() float64 {
return 1.0 + rand.NormFloat64()
})

View File

@ -29,6 +29,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/http"
"path"
"strconv"
@ -117,10 +118,7 @@ func DecryptETags(ctx context.Context, k *kms.KMS, objects []ObjectInfo) error {
names = make([]string, 0, BatchSize)
)
for len(objects) > 0 {
N := BatchSize
if len(objects) < BatchSize {
N = len(objects)
}
N := min(len(objects), BatchSize)
batch := objects[:N]
// We have to decrypt only ETags of SSE-S3 single-part
@ -317,9 +315,7 @@ func rotateKey(ctx context.Context, oldKey []byte, newKeyID string, newKey []byt
// of the client provided context and add the bucket
// key, if not present.
kmsCtx := kms.Context{}
for k, v := range cryptoCtx {
kmsCtx[k] = v
}
maps.Copy(kmsCtx, cryptoCtx)
if _, ok := kmsCtx[bucket]; !ok {
kmsCtx[bucket] = path.Join(bucket, object)
}
@ -389,9 +385,7 @@ func newEncryptMetadata(ctx context.Context, kind crypto.Type, keyID string, key
// of the client provided context and add the bucket
// key, if not present.
kmsCtx := kms.Context{}
for k, v := range cryptoCtx {
kmsCtx[k] = v
}
maps.Copy(kmsCtx, cryptoCtx)
if _, ok := kmsCtx[bucket]; !ok {
kmsCtx[bucket] = path.Join(bucket, object)
}
@ -456,7 +450,7 @@ func setEncryptionMetadata(r *http.Request, bucket, object string, metadata map[
}
}
_, err = newEncryptMetadata(r.Context(), kind, keyID, key, bucket, object, metadata, kmsCtx)
return
return err
}
// EncryptRequest takes the client provided content and encrypts the data
@ -861,7 +855,7 @@ func tryDecryptETag(key []byte, encryptedETag string, sses3 bool) string {
func (o *ObjectInfo) GetDecryptedRange(rs *HTTPRangeSpec) (encOff, encLength, skipLen int64, seqNumber uint32, partStart int, err error) {
if _, ok := crypto.IsEncrypted(o.UserDefined); !ok {
err = errors.New("Object is not encrypted")
return
return encOff, encLength, skipLen, seqNumber, partStart, err
}
if rs == nil {
@ -879,7 +873,7 @@ func (o *ObjectInfo) GetDecryptedRange(rs *HTTPRangeSpec) (encOff, encLength, sk
partSize, err = sio.DecryptedSize(uint64(part.Size))
if err != nil {
err = errObjectTampered
return
return encOff, encLength, skipLen, seqNumber, partStart, err
}
sizes[i] = int64(partSize)
decObjSize += int64(partSize)
@ -889,7 +883,7 @@ func (o *ObjectInfo) GetDecryptedRange(rs *HTTPRangeSpec) (encOff, encLength, sk
partSize, err = sio.DecryptedSize(uint64(o.Size))
if err != nil {
err = errObjectTampered
return
return encOff, encLength, skipLen, seqNumber, partStart, err
}
sizes = []int64{int64(partSize)}
decObjSize = sizes[0]
@ -898,7 +892,7 @@ func (o *ObjectInfo) GetDecryptedRange(rs *HTTPRangeSpec) (encOff, encLength, sk
var off, length int64
off, length, err = rs.GetOffsetLength(decObjSize)
if err != nil {
return
return encOff, encLength, skipLen, seqNumber, partStart, err
}
// At this point, we have:

View File

@ -384,7 +384,7 @@ func TestGetDecryptedRange(t *testing.T) {
// Simple useful utilities
repeat = func(k int64, n int) []int64 {
a := []int64{}
for i := 0; i < n; i++ {
for range n {
a = append(a, k)
}
return a
@ -471,10 +471,7 @@ func TestGetDecryptedRange(t *testing.T) {
// round up the lbPartOffset
// to the end of the
// corresponding DARE package
lbPkgEndOffset := lbPartOffset - (lbPartOffset % pkgSz) + pkgSz
if lbPkgEndOffset > v {
lbPkgEndOffset = v
}
lbPkgEndOffset := min(lbPartOffset-(lbPartOffset%pkgSz)+pkgSz, v)
bytesToDrop := v - lbPkgEndOffset
// Last segment to update `l`
@ -486,7 +483,7 @@ func TestGetDecryptedRange(t *testing.T) {
cumulativeSum += v
cumulativeEncSum += getEncSize(v)
}
return
return o, l, skip, sn, ps
}
for i, test := range testMPs {

View File

@ -22,7 +22,7 @@ import (
"fmt"
"net/url"
"runtime"
"sort"
"slices"
"strings"
"github.com/cespare/xxhash/v2"
@ -122,9 +122,7 @@ func possibleSetCountsWithSymmetry(setCounts []uint64, argPatterns []ellipses.Ar
// eyes that we prefer a sorted setCount slice for the
// subsequent function to figure out the right common
// divisor, it avoids loops.
sort.Slice(setCounts, func(i, j int) bool {
return setCounts[i] < setCounts[j]
})
slices.Sort(setCounts)
return setCounts
}
@ -445,7 +443,7 @@ func buildDisksLayoutFromConfFile(pools []poolArgs) (layout disksLayout, err err
layout: setArgs,
})
}
return
return layout, err
}
// mergeDisksLayoutFromArgs supports with and without ellipses transparently.
@ -477,7 +475,7 @@ func mergeDisksLayoutFromArgs(args []string, ctxt *serverCtxt) (err error) {
legacy: true,
pools: []poolDisksLayout{{layout: setArgs, cmdline: strings.Join(args, " ")}},
}
return
return err
}
for _, arg := range args {
@ -491,7 +489,7 @@ func mergeDisksLayoutFromArgs(args []string, ctxt *serverCtxt) (err error) {
}
ctxt.Layout.pools = append(ctxt.Layout.pools, poolDisksLayout{cmdline: arg, layout: setArgs})
}
return
return err
}
// CreateServerEndpoints - validates and creates new endpoints from input args, supports

View File

@ -55,7 +55,6 @@ func TestCreateServerEndpoints(t *testing.T) {
}
for i, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
srvCtxt := serverCtxt{}
err := mergeDisksLayoutFromArgs(testCase.args, &srvCtxt)
@ -85,7 +84,6 @@ func TestGetDivisibleSize(t *testing.T) {
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
gotGCD := getDivisibleSize(testCase.totalSizes)
if testCase.result != gotGCD {
@ -172,7 +170,6 @@ func TestGetSetIndexesEnvOverride(t *testing.T) {
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
argPatterns := make([]ellipses.ArgPattern, len(testCase.args))
for i, arg := range testCase.args {
@ -294,7 +291,6 @@ func TestGetSetIndexes(t *testing.T) {
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
argPatterns := make([]ellipses.ArgPattern, len(testCase.args))
for i, arg := range testCase.args {
@ -637,7 +633,6 @@ func TestParseEndpointSet(t *testing.T) {
}
for _, testCase := range testCases {
testCase := testCase
t.Run("", func(t *testing.T) {
gotEs, err := parseEndpointSet(0, testCase.arg)
if err != nil && testCase.success {

View File

@ -267,7 +267,7 @@ func (l EndpointServerPools) ESCount() (count int) {
for _, p := range l {
count += p.SetCount
}
return
return count
}
// GetNodes returns a sorted list of nodes in this cluster
@ -297,7 +297,7 @@ func (l EndpointServerPools) GetNodes() (nodes []Node) {
sort.Slice(nodes, func(i, j int) bool {
return nodes[i].Host < nodes[j].Host
})
return
return nodes
}
// GetPoolIdx return pool index
@ -588,7 +588,7 @@ func (endpoints Endpoints) GetAllStrings() (all []string) {
for _, e := range endpoints {
all = append(all, e.String())
}
return
return all
}
func hostResolveToLocalhost(endpoint Endpoint) bool {

View File

@ -312,7 +312,6 @@ func TestCreateEndpoints(t *testing.T) {
}
for i, testCase := range testCases {
i := i
testCase := testCase
t.Run("", func(t *testing.T) {
var srvCtxt serverCtxt

View File

@ -69,7 +69,7 @@ func NewErasure(ctx context.Context, dataBlocks, parityBlocks int, blockSize int
})
return enc
}
return
return e, err
}
// EncodeData encodes the given data and returns the erasure-coded data.
@ -136,10 +136,7 @@ func (e *Erasure) ShardFileOffset(startOffset, length, totalLength int64) int64
shardSize := e.ShardSize()
shardFileSize := e.ShardFileSize(totalLength)
endShard := (startOffset + length) / e.blockSize
tillOffset := endShard*shardSize + shardSize
if tillOffset > shardFileSize {
tillOffset = shardFileSize
}
tillOffset := min(endShard*shardSize+shardSize, shardFileSize)
return tillOffset
}

View File

@ -30,7 +30,6 @@ func (er erasureObjects) getOnlineDisks() (newDisks []StorageAPI) {
var mu sync.Mutex
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for _, i := range r.Perm(len(disks)) {
i := i
wg.Add(1)
go func() {
defer wg.Done()

View File

@ -251,7 +251,7 @@ func TestErasureDecodeRandomOffsetLength(t *testing.T) {
buf := &bytes.Buffer{}
// Verify erasure.Decode() for random offsets and lengths.
for i := 0; i < iterations; i++ {
for range iterations {
offset := r.Int63n(length)
readLen := r.Int63n(length - offset)
@ -308,17 +308,16 @@ func benchmarkErasureDecode(data, parity, dataDown, parityDown int, size int64,
b.Fatalf("failed to create erasure test file: %v", err)
}
for i := 0; i < dataDown; i++ {
for i := range dataDown {
writers[i] = nil
}
for i := data; i < data+parityDown; i++ {
writers[i] = nil
}
b.ResetTimer()
b.SetBytes(size)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for b.Loop() {
bitrotReaders := make([]io.ReaderAt, len(disks))
for index, disk := range disks {
if writers[index] == nil {

View File

@ -172,17 +172,16 @@ func benchmarkErasureEncode(data, parity, dataDown, parityDown int, size int64,
buffer := make([]byte, blockSizeV2, 2*blockSizeV2)
content := make([]byte, size)
for i := 0; i < dataDown; i++ {
for i := range dataDown {
disks[i] = OfflineDisk
}
for i := data; i < data+parityDown; i++ {
disks[i] = OfflineDisk
}
b.ResetTimer()
b.SetBytes(size)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for b.Loop() {
writers := make([]io.Writer, len(disks))
for i, disk := range disks {
if disk == OfflineDisk {

View File

@ -102,7 +102,7 @@ func TestErasureHeal(t *testing.T) {
// setup stale disks for the test case
staleDisks := make([]StorageAPI, len(disks))
copy(staleDisks, disks)
for j := 0; j < len(staleDisks); j++ {
for j := range staleDisks {
if j < test.offDisks {
readers[j] = nil
} else {

View File

@ -283,7 +283,7 @@ func countPartNotSuccess(partErrs []int) (c int) {
c++
}
}
return
return c
}
// checkObjectWithAllParts sets partsMetadata and onlineDisks when xl.meta is inexistant/corrupted or outdated
@ -436,5 +436,5 @@ func checkObjectWithAllParts(ctx context.Context, onlineDisks []StorageAPI, part
dataErrsByDisk[disk][part] = dataErrsByPart[part][disk]
}
}
return
return dataErrsByDisk, dataErrsByPart
}

View File

@ -175,7 +175,7 @@ func TestListOnlineDisks(t *testing.T) {
fourNanoSecs := time.Unix(4, 0).UTC()
modTimesThreeNone := make([]time.Time, 16)
modTimesThreeFour := make([]time.Time, 16)
for i := 0; i < 16; i++ {
for i := range 16 {
// Have 13 good xl.meta, 12 for default parity count = 4 (EC:4) and one
// to be tampered with.
if i > 12 {
@ -244,7 +244,6 @@ func TestListOnlineDisks(t *testing.T) {
}
for i, test := range testCases {
test := test
t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) {
_, err = obj.PutObject(ctx, bucket, object, mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), "", ""), ObjectOptions{})
if err != nil {
@ -350,7 +349,7 @@ func TestListOnlineDisksSmallObjects(t *testing.T) {
fourNanoSecs := time.Unix(4, 0).UTC()
modTimesThreeNone := make([]time.Time, 16)
modTimesThreeFour := make([]time.Time, 16)
for i := 0; i < 16; i++ {
for i := range 16 {
// Have 13 good xl.meta, 12 for default parity count = 4 (EC:4) and one
// to be tampered with.
if i > 12 {
@ -419,7 +418,6 @@ func TestListOnlineDisksSmallObjects(t *testing.T) {
}
for i, test := range testCases {
test := test
t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) {
_, err := obj.PutObject(ctx, bucket, object,
mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), "", ""), ObjectOptions{})
@ -753,7 +751,7 @@ func TestCommonParities(t *testing.T) {
}
for idx, test := range tests {
var metaArr []FileInfo
for i := 0; i < 12; i++ {
for i := range 12 {
fi := test.fi1
if i%2 == 0 {
fi = test.fi2

View File

@ -116,7 +116,6 @@ func (er erasureObjects) listAndHeal(ctx context.Context, bucket, prefix string,
func listAllBuckets(ctx context.Context, storageDisks []StorageAPI, healBuckets *xsync.MapOf[string, VolInfo], readQuorum int) error {
g := errgroup.WithNErrs(len(storageDisks))
for index := range storageDisks {
index := index
g.Go(func() error {
if storageDisks[index] == nil {
// we ignore disk not found errors
@ -966,7 +965,7 @@ func danglingMetaErrsCount(cerrs []error) (notFoundCount int, nonActionableCount
nonActionableCount++
}
}
return
return notFoundCount, nonActionableCount
}
func danglingPartErrsCount(results []int) (notFoundCount int, nonActionableCount int) {
@ -981,7 +980,7 @@ func danglingPartErrsCount(results []int) (notFoundCount int, nonActionableCount
nonActionableCount++
}
}
return
return notFoundCount, nonActionableCount
}
// Object is considered dangling/corrupted if and only

View File

@ -296,7 +296,6 @@ func TestIsObjectDangling(t *testing.T) {
// Add new cases as seen
}
for _, testCase := range testCases {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
gotMeta, dangling := isObjectDangling(testCase.metaArr, testCase.errs, testCase.dataErrs)
if !gotMeta.Equals(testCase.expectedMeta) {

View File

@ -204,7 +204,6 @@ func readAllFileInfo(ctx context.Context, disks []StorageAPI, origbucket string,
g := errgroup.WithNErrs(len(disks))
// Read `xl.meta` in parallel across disks.
for index := range disks {
index := index
g.Go(func() (err error) {
if disks[index] == nil {
return errDiskNotFound

View File

@ -55,7 +55,7 @@ func TestDiskCount(t *testing.T) {
// of errors into a single maximal error with in the list.
func TestReduceErrs(t *testing.T) {
canceledErrs := make([]error, 0, 5)
for i := 0; i < 5; i++ {
for i := range 5 {
canceledErrs = append(canceledErrs, fmt.Errorf("error %d: %w", i, context.Canceled))
}
// List all of all test cases to validate various cases of reduce errors.
@ -222,7 +222,7 @@ func Test_hashOrder(t *testing.T) {
var tmp [16]byte
rng.Read(tmp[:])
prefix := hex.EncodeToString(tmp[:])
for i := 0; i < 10000; i++ {
for range 10000 {
rng.Read(tmp[:])
y := hashOrder(fmt.Sprintf("%s/%x", prefix, hex.EncodeToString(tmp[:3])), x)

View File

@ -408,7 +408,6 @@ func writeAllMetadataWithRevert(ctx context.Context, disks []StorageAPI, origbuc
// Start writing `xl.meta` to all disks in parallel.
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return errDiskNotFound
@ -522,7 +521,7 @@ func listObjectParities(partsMetadata []FileInfo, errs []error) (parities []int)
parities[index] = metadata.Erasure.ParityBlocks
}
}
return
return parities
}
// Returns per object readQuorum and writeQuorum

View File

@ -189,7 +189,7 @@ func TestFindFileInfoInQuorum(t *testing.T) {
commonNumVersions := 2
numVersionsInQuorum := make([]int, 16)
numVersionsNoQuorum := make([]int, 16)
for i := 0; i < 16; i++ {
for i := range 16 {
if i < 4 {
continue
}
@ -269,7 +269,6 @@ func TestFindFileInfoInQuorum(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run("", func(t *testing.T) {
fi, err := findFileInfoInQuorum(t.Context(), test.fis, test.modTime, "", test.expectedQuorum)
_, ok1 := err.(InsufficientReadQuorum)
@ -316,7 +315,7 @@ func TestTransitionInfoEquals(t *testing.T) {
}
var i uint
for i = 0; i < 8; i++ {
for i = range uint(8) {
fi := FileInfo{
TransitionTier: inputs[0].tier,
TransitionedObjName: inputs[0].remoteObjName,

View File

@ -322,7 +322,7 @@ func (er erasureObjects) ListMultipartUploads(ctx context.Context, bucket, objec
uploads = append(uploads, MultipartInfo{
Bucket: bucket,
Object: object,
UploadID: base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf("%s.%s", globalDeploymentID(), uploadID))),
UploadID: base64.RawURLEncoding.EncodeToString(fmt.Appendf(nil, "%s.%s", globalDeploymentID(), uploadID)),
Initiated: startTime,
})
populatedUploadIDs.Add(uploadID)
@ -393,6 +393,12 @@ func (er erasureObjects) newMultipartUpload(ctx context.Context, bucket string,
if err != nil && !isErrVersionNotFound(err) && !isErrObjectNotFound(err) && !isErrReadQuorum(err) {
return nil, err
}
// if object doesn't exist return error for If-Match conditional requests
// If-None-Match should be allowed to proceed for non-existent objects
if err != nil && opts.HasIfMatch && (isErrObjectNotFound(err) || isErrVersionNotFound(err)) {
return nil, err
}
}
userDefined := cloneMSS(opts.UserDefined)
@ -498,7 +504,7 @@ func (er erasureObjects) newMultipartUpload(ctx context.Context, bucket string,
partsMetadata[index].Metadata = userDefined
}
uploadUUID := fmt.Sprintf("%sx%d", mustGetUUID(), modTime.UnixNano())
uploadID := base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf("%s.%s", globalDeploymentID(), uploadUUID)))
uploadID := base64.RawURLEncoding.EncodeToString(fmt.Appendf(nil, "%s.%s", globalDeploymentID(), uploadUUID))
uploadIDPath := er.getUploadIDDir(bucket, object, uploadUUID)
// Write updated `xl.meta` to all disks.
@ -540,7 +546,6 @@ func (er erasureObjects) renamePart(ctx context.Context, disks []StorageAPI, src
// Rename file on all underlying storage disks.
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return errDiskNotFound
@ -820,7 +825,6 @@ func (er erasureObjects) listParts(ctx context.Context, onlineDisks []StorageAPI
objectParts := make([][]string, len(onlineDisks))
// List uploaded parts from drives.
for index := range onlineDisks {
index := index
g.Go(func() (err error) {
if onlineDisks[index] == nil {
return errDiskNotFound
@ -995,7 +999,6 @@ func readParts(ctx context.Context, disks []StorageAPI, bucket string, partMetaP
objectPartInfos := make([][]*ObjectPartInfo, len(disks))
// Rename file on all underlying storage disks.
for index := range disks {
index := index
g.Go(func() (err error) {
if disks[index] == nil {
return errDiskNotFound
@ -1114,6 +1117,12 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
if err != nil && !isErrVersionNotFound(err) && !isErrObjectNotFound(err) && !isErrReadQuorum(err) {
return ObjectInfo{}, err
}
// if object doesn't exist return error for If-Match conditional requests
// If-None-Match should be allowed to proceed for non-existent objects
if err != nil && opts.HasIfMatch && (isErrObjectNotFound(err) || isErrVersionNotFound(err)) {
return ObjectInfo{}, err
}
}
fi, partsMetadata, err := er.checkUploadIDExists(ctx, bucket, object, uploadID, true)
@ -1161,6 +1170,7 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
Err: fmt.Errorf("checksum type mismatch. got %q (%s) expected %q (%s)", checksumType.String(), checksumType.ObjType(), opts.WantChecksum.Type.String(), opts.WantChecksum.Type.ObjType()),
}
}
checksumType |= hash.ChecksumMultipart | hash.ChecksumIncludesMultipart
}
var checksumCombined []byte
@ -1509,17 +1519,10 @@ func (er erasureObjects) AbortMultipartUpload(ctx context.Context, bucket, objec
auditObjectErasureSet(ctx, "AbortMultipartUpload", object, &er)
}
// Validates if upload ID exists.
if _, _, err = er.checkUploadIDExists(ctx, bucket, object, uploadID, false); err != nil {
if errors.Is(err, errVolumeNotFound) {
return toObjectErr(err, bucket)
}
return toObjectErr(err, bucket, object, uploadID)
}
// Cleanup all uploaded parts.
er.deleteAll(ctx, minioMetaMultipartBucket, er.getUploadIDDir(bucket, object, uploadID))
defer er.deleteAll(ctx, minioMetaMultipartBucket, er.getUploadIDDir(bucket, object, uploadID))
// Successfully purged.
return nil
// Validates if upload ID exists.
_, _, err = er.checkUploadIDExists(ctx, bucket, object, uploadID, false)
return toObjectErr(err, bucket, object, uploadID)
}

View File

@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/http"
"path"
"runtime"
@ -542,7 +543,6 @@ func (er erasureObjects) deleteIfDangling(ctx context.Context, bucket, object st
disks := er.getDisks()
g := errgroup.WithNErrs(len(disks))
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return errDiskNotFound
@ -575,7 +575,6 @@ func readAllRawFileInfo(ctx context.Context, disks []StorageAPI, bucket, object
rawFileInfos := make([]RawFileInfo, len(disks))
g := errgroup.WithNErrs(len(disks))
for index := range disks {
index := index
g.Go(func() (err error) {
if disks[index] == nil {
return errDiskNotFound
@ -1029,7 +1028,6 @@ func renameData(ctx context.Context, disks []StorageAPI, srcBucket, srcEntry str
dataDirs := make([]string, len(disks))
// Rename file on all underlying storage disks.
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return errDiskNotFound
@ -1279,6 +1277,12 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
if err != nil && !isErrVersionNotFound(err) && !isErrObjectNotFound(err) && !isErrReadQuorum(err) {
return objInfo, err
}
// if object doesn't exist return error for If-Match conditional requests
// If-None-Match should be allowed to proceed for non-existent objects
if err != nil && opts.HasIfMatch && (isErrObjectNotFound(err) || isErrVersionNotFound(err)) {
return objInfo, err
}
}
// Validate input data size and it can never be less than -1.
@ -1631,7 +1635,6 @@ func (er erasureObjects) deleteObjectVersion(ctx context.Context, bucket, object
g := errgroup.WithNErrs(len(disks))
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return errDiskNotFound
@ -1836,7 +1839,6 @@ func (er erasureObjects) commitRenameDataDir(ctx context.Context, bucket, object
}
g := errgroup.WithNErrs(len(onlineDisks))
for index := range onlineDisks {
index := index
g.Go(func() error {
if onlineDisks[index] == nil {
return nil
@ -1862,7 +1864,6 @@ func (er erasureObjects) deletePrefix(ctx context.Context, bucket, prefix string
g := errgroup.WithNErrs(len(disks))
for index := range disks {
index := index
g.Go(func() error {
if disks[index] == nil {
return nil
@ -2222,9 +2223,7 @@ func (er erasureObjects) PutObjectMetadata(ctx context.Context, bucket, object s
return ObjectInfo{}, err
}
}
for k, v := range objInfo.UserDefined {
fi.Metadata[k] = v
}
maps.Copy(fi.Metadata, objInfo.UserDefined)
fi.ModTime = opts.MTime
fi.VersionID = opts.VersionID
@ -2294,9 +2293,7 @@ func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object strin
fi.Metadata[xhttp.AmzObjectTagging] = tags
fi.ReplicationState = opts.PutReplicationState()
for k, v := range opts.UserDefined {
fi.Metadata[k] = v
}
maps.Copy(fi.Metadata, opts.UserDefined)
if err = er.updateObjectMeta(ctx, bucket, object, fi, onlineDisks); err != nil {
return ObjectInfo{}, toObjectErr(err, bucket, object)
@ -2314,7 +2311,6 @@ func (er erasureObjects) updateObjectMetaWithOpts(ctx context.Context, bucket, o
// Start writing `xl.meta` to all disks in parallel.
for index := range onlineDisks {
index := index
g.Go(func() error {
if onlineDisks[index] == nil {
return errDiskNotFound

View File

@ -112,7 +112,6 @@ func TestErasureDeleteObjectBasic(t *testing.T) {
t.Fatalf("Erasure Object upload failed: <ERROR> %s", err)
}
for _, test := range testCases {
test := test
t.Run("", func(t *testing.T) {
_, err := xl.GetObjectInfo(ctx, "bucket", "dir/obj", ObjectOptions{})
if err != nil {
@ -625,7 +624,7 @@ func TestGetObjectNoQuorum(t *testing.T) {
t.Fatal(err)
}
for f := 0; f < 2; f++ {
for f := range 2 {
diskErrors := make(map[int]error)
for i := 0; i <= f; i++ {
diskErrors[i] = nil
@ -774,7 +773,7 @@ func TestPutObjectNoQuorum(t *testing.T) {
// in a 16 disk Erasure setup. The original disks are 'replaced' with
// naughtyDisks that fail after 'f' successful StorageAPI method
// invocations, where f - [0,4)
for f := 0; f < 2; f++ {
for f := range 2 {
diskErrors := make(map[int]error)
for i := 0; i <= f; i++ {
diskErrors[i] = nil
@ -837,7 +836,7 @@ func TestPutObjectNoQuorumSmall(t *testing.T) {
// in a 16 disk Erasure setup. The original disks are 'replaced' with
// naughtyDisks that fail after 'f' successful StorageAPI method
// invocations, where f - [0,2)
for f := 0; f < 2; f++ {
for f := range 2 {
t.Run("exec-"+strconv.Itoa(f), func(t *testing.T) {
diskErrors := make(map[int]error)
for i := 0; i <= f; i++ {
@ -1109,7 +1108,6 @@ func testObjectQuorumFromMeta(obj ObjectLayer, instanceType string, dirs []strin
{parts7, errs7, 11, 11, parts7SC, nil},
}
for _, tt := range tests {
tt := tt
t.(*testing.T).Run("", func(t *testing.T) {
globalStorageClass.Update(tt.storageClassCfg)
actualReadQuorum, actualWriteQuorum, err := objectQuorumFromMeta(ctx, tt.parts, tt.errs, storageclass.DefaultParityBlocks(len(erasureDisks)))

View File

@ -25,6 +25,7 @@ import (
"io"
"math/rand"
"net/http"
"slices"
"sort"
"strings"
"time"
@ -117,12 +118,7 @@ func (pd *PoolDecommissionInfo) bucketPop(bucket string) bool {
}
func (pd *PoolDecommissionInfo) isBucketDecommissioned(bucket string) bool {
for _, b := range pd.DecommissionedBuckets {
if b == bucket {
return true
}
}
return false
return slices.Contains(pd.DecommissionedBuckets, bucket)
}
func (pd *PoolDecommissionInfo) bucketPush(bucket decomBucketInfo) {
@ -237,7 +233,7 @@ func (p poolMeta) ResumeBucketObject(idx int) (bucket, object string) {
bucket = p.Pools[idx].Decommission.Bucket
object = p.Pools[idx].Decommission.Object
}
return
return bucket, object
}
func (p *poolMeta) TrackCurrentBucketObject(idx int, bucket string, object string) {
@ -572,6 +568,7 @@ func newPoolMeta(z *erasureServerPools, prevMeta poolMeta) poolMeta {
for _, currentPool := range prevMeta.Pools {
// Preserve any current pool status.
if currentPool.CmdLine == pool.endpoints.CmdLine {
currentPool.ID = idx
newMeta.Pools = append(newMeta.Pools, currentPool)
skip = true
break
@ -792,8 +789,6 @@ func (z *erasureServerPools) decommissionPool(ctx context.Context, idx int, pool
}
for setIdx, set := range pool.sets {
set := set
filterLifecycle := func(bucket, object string, fi FileInfo) bool {
if lc == nil {
return false
@ -901,7 +896,7 @@ func (z *erasureServerPools) decommissionPool(ctx context.Context, idx int, pool
}
// gr.Close() is ensured by decommissionObject().
for try := 0; try < 3; try++ {
for range 3 {
if version.IsRemote() {
if err := z.DecomTieredObject(ctx, bi.Name, version.Name, version, ObjectOptions{
VersionID: versionID,

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"github.com/tinylib/msgp/msgp"
)

View File

@ -1,7 +1,7 @@
package cmd
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
package cmd
import (
"bytes"
"testing"

Some files were not shown because too many files have changed in this diff Show More