Help us shape the future of Go! Take the 2026 Go Developer Survey

s3

package
v0.1.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Overview

Package s3 implements the Destination interface for S3 and S3-compatible stores (AWS, MinIO, Wasabi, Backblaze B2, IDrive). It is create-only: there is no delete or overwrite path. Credentials come from the AWS SDK default chain, static keys (S3-compatible) are supplied via AWS_* env, never hand-resolved here.

Index

Constants

View Source
const (

	// MinPartSize and MaxPartSize are S3's own bounds on a part, and so on both settings.
	MinPartSize = 5 << 20
	MaxPartSize = 5 << 30
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Backend

type Backend struct {
	// contains filtered or unexported fields
}

Backend is a create-only S3 Destination.

func New

func New(ctx context.Context, opts Options, logger *slog.Logger) (*Backend, error)

New builds an S3 backend using the default credential chain.

func (*Backend) Get

func (b *Backend) Get(ctx context.Context, key string) (io.ReadCloser, error)

Get opens key for reading (read-only). Caller closes the reader.

func (*Backend) LimitResponses added in v0.1.21

func (b *Backend) LimitResponses(limit int64)

LimitResponses caps every response body b reads at limit bytes from here on: an answer that runs past it fails with dest.ErrResponseTooLarge rather than being read to its end. Call it before b is in use. A limit of zero or less leaves b as it is.

It is for a caller that reads only a store's short answers and must not be held by a long one: `gitdr doctor`, pointed at an endpoint it has no reason to trust yet. Backup never calls it, since a GetObject body is a whole bundle. Uncapped, the SDK reads all of an answer: an error body is copied into memory whole, and every body is drained to its end before it is closed.

The client is rebuilt from its own options, so everything else about it, the endpoint, the credentials, the retries and the transport's timeouts, stays as New made it.

func (*Backend) List

func (b *Backend) List(ctx context.Context, prefix string) ([]dest.Object, error)

List returns objects under prefix (read-only).

func (*Backend) ListPage added in v0.1.21

func (b *Backend) ListPage(ctx context.Context, prefix string, limit int) ([]dest.Object, bool, error)

ListPage lists at most limit objects under prefix with one ListObjectsV2 request (read-only), and says whether the store reported more. It never sends the continuation token back, so on a bucket of a million objects it is one request, and on a store that answers every page with another one it is still one.

func (*Backend) ObserveRetention added in v0.1.16

func (b *Backend) ObserveRetention(ctx context.Context, key string) (dest.RetentionObservation, time.Time, error)

ObserveRetention asks S3 what retention is actually on an object gitdr wrote.

`GetObjectRetention` rather than `HeadObject`, and the difference decides whether this check is usable at all. HeadObject returns `x-amz-object-lock-mode` **only if the caller holds `s3:GetObjectRetention`** - without it the response is a 200 with the headers silently omitted, byte-identical to an object that carries no retention. SPEC tells every operator to scope destination credentials create/put-only, so a HEAD-based check would report "the destination accepted a write it did not retain" about correctly configured, genuinely protected buckets belonging to the operators who followed that advice. That is the unearned negative WormVerdict exists to prevent, and it would teach people to ignore the one warning that matters.

`?retention` fails distinguishably instead:

NoSuchObjectLockConfiguration  the store implements the question and this object holds
                               nothing. An earned negative. AWS answers it with a 404 and
                               MinIO with a 400.
ObjectLockConfigurationNotFoundError
                               the same negative from Backblaze B2, a 404. AWS gives this code
                               to the bucket's lock question, which VerifyWorm asks; here it
                               answers a question about one object.
AccessDenied / NotImplemented  a refusal, and a refusal is not a no.
anything else                  unclassified, and unclassified is not a no either.

func (*Backend) PutImmutable

func (b *Backend) PutImmutable(ctx context.Context, key string, r io.Reader, size int64, ret dest.Retention) (dest.PutResult, error)

PutImmutable creates key, create-only, never overwriting or deleting. Object Lock retention is applied only when ret carries a retain-until (i.e. the bucket is immutable); on the non-WORM adoption path we write plainly, because sending lock headers to a bucket without Object Lock is a 400. An explicit CRC32 checksum is always sent: AWS and some S3-compatible stores (Backblaze B2) require Content-MD5 or an x-amz-checksum header on Object Lock PutObject requests.

The CRC32 is computed here and sent as a header, so the body goes as it is, with its length. Asked for the algorithm alone, the SDK computes the checksum on the way out, and over TLS it sends the body aws-chunked, the whole object as one chunk, with the checksum in a trailer (service/internal/checksum v1.11.3: middleware_compute_input_checksum.go, lines 163-177, and aws_chunked_encoding.go, lines 90-111). AWS takes a chunk of any size; MinIO refuses one over 16 MiB, so no object over 16 MiB could be written to MinIO over TLS. A checksum header already on the request turns the trailer off (the same file, lines 131-139 and 285-290).

func (*Backend) VerifyWorm

func (b *Backend) VerifyWorm(ctx context.Context) (dest.WormStatus, error)

VerifyWorm probes bucket Object Lock. A missing lock config is reported as not-locked once a listing shows the bucket exists (so the operator can override); other failures, an answer that is not S3's among them, are returned as errors.

type Options

type Options struct {
	Bucket       string
	Region       string // defaults to us-east-1 (also fine for MinIO)
	Endpoint     string // empty = AWS; set for MinIO/Wasabi/B2/IDrive
	UsePathStyle bool   // true for MinIO and most S3-compatible stores
	// MultipartThreshold is the size above which an object is written in parts; 0 is 4 GiB.
	// PartSize is the smallest part; 0 is 64 MiB, and a larger object gets larger parts so it
	// stays under 9,000 of them. Both are bounded by MinPartSize and MaxPartSize. They exist so
	// a test can write in parts without writing gigabytes.
	MultipartThreshold int64
	PartSize           int64
}

Options configures the S3 backend. Credentials are intentionally absent: they are resolved by the SDK default chain (env, IRSA/Pod Identity, instance profile, SSO).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL