Documentation
¶
Overview ¶
Package ociartifact acquires first-class Argo CD OCI artifact sources (repoURL "oci://…" without chart:) by wrapping the vendored Argo CD OCI client. Revision resolution and extraction guards follow argo-cd v3.4.5 util/oci/client.go; the image cache is a drydock-owned layout under the OCI cache root so `drydock cache` can list and prune it.
Index ¶
- Constants
- func DefaultCacheDir() (string, error)
- func EntryKey(repoURL, version string) string
- func EntryPath(cacheDir, repoURL, version string) string
- func ImageTarPath(entryPath string) string
- func IsDigest(revision string) bool
- func IsOCIURL(repoURL string) bool
- func NormalizeURL(repoURL string) string
- func RedactURL(repoURL string) string
- func ResolveCacheDir(cacheDir string, forbiddenRoots []string) (string, error)
- type Acquirer
- type Credentials
- type DefaultAcquirer
- type Options
Constants ¶
const EntryKind = "image"
EntryKind is the cache metadata kind recorded for OCI artifact image entries (source "oci", kind "image").
Variables ¶
This section is empty.
Functions ¶
func DefaultCacheDir ¶
func ImageTarPath ¶
ImageTarPath returns the cached image tar location inside an entry.
func IsOCIURL ¶
IsOCIURL reports whether repoURL names an OCI registry source. It is total over oci:// spellings: surrounding whitespace and scheme casing do not change classification, so no spelling can fall through to the local path-exists or git-acquisition branches. Argo CD matches the exact lowercase prefix (v1alpha1 types.go:317-319); accepting case variants only widens classification, never re-routes a URL argo would treat as OCI.
func NormalizeURL ¶
NormalizeURL canonicalizes an OCI repository URL for cache keys and records: whitespace and trailing slashes trimmed, scheme dropped (the argo client keys its cache on the schemeless repo path, util/oci/client.go:125).
Types ¶
type Acquirer ¶
type Acquirer interface {
Resolve(ctx context.Context, repoURL, revision string, opts Options) (string, error)
Extract(ctx context.Context, repoURL, digest string, opts Options) (string, func(), error)
}
Acquirer is the OCI artifact acquisition seam. Resolve turns a tag, semver constraint, or digest into a concrete digest; Extract materializes the artifact content for that digest into a directory and returns a release callback for it.
type Credentials ¶
type Credentials struct {
Username string
Password string
RegistryConfig string
CAFile string
ClientCertFile string
ClientKeyFile string
InsecureSkipVerify bool
}
Credentials carries OCI registry auth and TLS material in flag-shaped form (file PATHS, not contents), mirroring chart.ChartCredentials. Auth comes from two sources: RegistryConfig is a Docker/Helm registry config file (`helm registry login` format) consulted per registry host by ForRepository, so one run can authenticate to several registries; the Username/Password pair is the global override, presented to every OCI artifact registry a run touches and short-circuiting the file whenever either half is set. The TLS fields remain one global set (helm/git parity).
func (Credentials) ForRepository ¶ added in v0.3.5
func (c Credentials) ForRepository(ctx context.Context, repoURL string) (Credentials, error)
ForRepository resolves the credentials to present to repoURL's registry. The explicit Username/Password pair wins for every host without opening the file; otherwise RegistryConfig is read through oras's own credential store — plain `auths` entries, legacy `https://host/` keys, `credsStore` and `credHelpers` — under the key `docker login` and `helm registry login` write for that host. A host without an entry stays anonymous. The file is validated here, at the first oci:// acquisition, rather than in Validate (see there). Once the file has been consulted the result carries RegistryConfig cleared, so the second call made by DefaultAcquirer.newClient is a no-op; with the explicit pair set it is a no-op by the first rule.
Two shapes fail loudly instead of degrading to an anonymous pull that would resurface later as an opaque 401 on the private registry: an identity/registry token entry (the vendored Argo client sends username and password only, util/oci/client.go:90-98,160-165 — helm forwards the whole credential, this client cannot), and a credential helper that cannot run (oras maps only "credentials not found" to the empty credential, native_store.go:87-91; an exec failure such as a missing docker-credential-<helper> binary surfaces with the helper named, kept via %w). DetectDefaultNativeStore stays false: helm sets it true, which for an auth-less file reads the OS keychain — ambient credentials by any definition. It is moot for real `helm registry login` files, which oras writes `credsStore` back into on the first native-store put.
func (Credentials) HTTPClient ¶ added in v0.3.1
func (c Credentials) HTTPClient() (client *http.Client, configured bool, err error)
HTTPClient builds the http.Client that OCI *Helm chart* pulls use, from the same --oci-* TLS flags the artifact path consumes. It reports configured = false when no TLS-implying flag is set, so the caller leaves the Helm OCI puller on helm's own default client. Credentials stay out of it: username/password remain artifact-only and OCI Helm chart auth remains --registry-config.
The pool rule differs from the artifact path deliberately. The vendored Argo client REPLACES the system pool with CAPath (client.go:482); for chart pulls the bundle is ADDED to the system pool, because a run that passes --oci-ca-file for a private artifact registry must keep pulling public charts from e.g. ghcr.io. A system pool that cannot be loaded is an error naming the flag rather than a silently narrowed pool.
func (Credentials) Validate ¶
func (c Credentials) Validate() error
Validate fails fast at request construction with errors naming the flag. The vendored client silently degrades on both mistakes guarded here: the AppendCertsFromPEM return for CAPath is ignored (vendored client.go:482 — a non-PEM CA file would silently yield an EMPTY RootCAs pool that also REPLACES the system pool), and CertData/KeyData are ignored unless BOTH are set (client.go:486 — a lone cert or key would be silently dropped). RegistryConfig is deliberately NOT checked here: Validate runs on every build and diff whether or not an oci:// source exists, so the file is validated lazily by ForRepository at the first OCI artifact acquisition — the same contract as the chart flow's validateRegistryConfig at first fetch. CI that passes --registry-config unconditionally keeps building git-only repositories.
type DefaultAcquirer ¶
type DefaultAcquirer struct{}
DefaultAcquirer wraps util/oci.NewClientWithLock. Every exported method of the argo client calls its embedded EventHandlers unconditionally and NewClientWithLock installs no defaults (util/oci/client.go:232,244,357, 373,410), so no-op handlers are mandatory. Resolve injects a drydock-owned prefetch-populated tags memo via WithIndexCache (see prefetchedTagsCache) — the upstream SetOCITags write path stores an empty read buffer (util/oci/client.go:450-452) and is deliberately ignored.
func (DefaultAcquirer) Extract ¶
func (a DefaultAcquirer) Extract(ctx context.Context, repoURL, digest string, opts Options) (string, func(), error)
Extract materializes the artifact content for digest. With a committed image tar cached, the argo client extracts locally without network; offline without a cached tar it fails with the offline cache miss contract error instead of letting the client reach the registry. Online, a cached tar that fails to extract (truncated by an interrupted earlier run or corrupted externally) is deleted and re-fetched once, so a bad tar never poisons every future run.
func (DefaultAcquirer) Resolve ¶
func (a DefaultAcquirer) Resolve(ctx context.Context, repoURL, revision string, opts Options) (string, error)
Resolve resolves revision to a digest. Digest-pinned revisions pass through without network. Online, resolution mirrors argo-cd v3.4.5 util/oci/client.go:384-407 exactly: the literal revision resolves first via a registry HEAD, and only when that fails does a constraint-shaped revision fall back to MaxVersion over the tag list. Offline, resolution is seam-level from records captured on earlier online runs, in the same exact-first order; the argo client is never constructed.
type Options ¶
type Options struct {
CacheDir string
Offline bool
ForbiddenRoots []string
Credentials Credentials
// OnAcquired is invoked by the production acquirer exactly once per real
// (non-memoized) successful Extract, with fromImageCache reporting whether
// the image tar was already cached before the call. Session memo hits never
// invoke it, which is what makes single-acquisition event assertions
// memo-sensitive. Fakes should call it when simulating an extraction.
OnAcquired func(fromImageCache bool)
}
Options carries per-call acquisition inputs, mirroring chart.Options.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ocitest provides hermetic OCI registry fixtures for drydock tests: an httptest-mounted distribution server plus artifact push helpers shaped like the artifacts the Argo CD OCI client consumes (helm chart artifacts, plain-manifest artifacts, and guard-violating variants).
|
Package ocitest provides hermetic OCI registry fixtures for drydock tests: an httptest-mounted distribution server plus artifact push helpers shaped like the artifacts the Argo CD OCI client consumes (helm chart artifacts, plain-manifest artifacts, and guard-violating variants). |