Documentation
¶
Overview ¶
Package s3 is Harbor's S3-compatible ArtifactStore driver. It is the operator-controlled-object-store production target — durable, multi-binary-friendly, and the canonical choice for cloud-native deployments. Speaks AWS S3, MinIO, Cloudflare R2, and any other S3-compatible API surface that the configured `Endpoint` and `UsePathStyle` knobs reach.
Built on `github.com/aws/aws-sdk-go-v2`. CGO_ENABLED=0 stays — the SDK is pure Go.
Object-key layout:
<prefix>/<tenant>/<user>/<session>/<task>/<namespace>/<id> <prefix>/<tenant>/<user>/<session>/<task>/<namespace>/<id>.meta.json
`<prefix>` is the operator-configured `S3Prefix` (may be empty — then the layout is rooted at the bucket itself). Empty `TaskID` becomes the literal segment `_` so the key hierarchy stays five levels deep below the namespace, parallel to the FS driver's `emptyTaskSentinel`. The `<id>.meta.json` sibling carries the `ArtifactRef` JSON (mime, size, sha, scope, namespace, source).
Identity-mandatory boundary. Tenant / user / session must be non-empty for Put*, Get, GetRef, Exists, Delete, and PresignGet. Empty `TaskID` is acceptable for session-scoped artifacts (matches the FS / InMem drivers).
404 semantics. `Get`, `GetRef`, `Exists`, `Delete` map S3 404 / `NoSuchKey` / `NotFound` to `(zero-value, false, nil)` — found-false is NOT an error, matching the FS driver's contract. Other errors (network, signature, permission) are wrapped and surfaced.
Dedup. `PutBytes` / `PutText` HEAD the destination key first; if the existing object's ETag (or sibling `.meta.json` SHA256) matches the new bytes' SHA, the existing ref is returned without re-uploading.
`Delete`. HEAD-then-batch-delete. Both blob + sibling meta land in a single `DeleteObjects` call. The HEAD pays a round trip but lets the driver return the same `(existed bool, error)` shape as the other drivers (S3's DeleteObject returns success regardless of prior existence).
Concurrency. The SDK's `*s3.Client` and `*s3.PresignClient` are safe for concurrent use. The driver itself adds only an atomic closed flag; the conformance suite's `Concurrent_PutGet_NoRace` gate (N=128 default) and the supplemental N=32 stress in `concurrent_test.go` prove the contract holds end-to-end.
Presigner capability. The driver implements `artifacts.Presigner` (`PresignGet` only — write-side presigned URLs are an attack surface intentionally not exposed at V1; see Phase 19 plan non-goals). Expiry bounded `[1 minute, 7 days]` — out-of-range returns a clear error.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
func New(cfg config.ArtifactsConfig) (artifacts.ArtifactStore, error)
New constructs an S3-compatible ArtifactStore. `cfg.S3Bucket` must be non-empty (validated upstream by `config.Validate` when `Driver == "s3"`; rechecked here defensively).
Builds an `*s3.Client` from `aws-sdk-go-v2`:
- When `cfg.S3AccessKeyID` and `cfg.S3SecretAccessKey` are both set, a `credentials.NewStaticCredentialsProvider` is used. Otherwise the SDK's default credential chain (env vars, IRSA, instance metadata, ~/.aws/credentials) applies.
- `cfg.S3Region` defaults to "us-east-1" when empty.
- `cfg.S3Endpoint` overrides the default AWS endpoint via `s3.Options.BaseEndpoint` — the modern AWS SDK v2 path that supersedes the deprecated `EndpointResolver`.
- `cfg.S3UsePathStyle` flips `s3.Options.UsePathStyle = true` for MinIO / older R2 buckets.
On construction, `New` issues a single `HeadBucket` to verify the bucket exists and the credentials work. A 404 is mapped to a clear "bucket not found at endpoint X" error rather than left as the SDK's raw exception.
Types ¶
This section is empty.