Current section
Files
Jump to
Current section
Files
lib/regc/oci/manifest.ex
defmodule Regc.Oci.Manifest do
@moduledoc """
A decoded and verified OCI image manifest or image index.
"""
alias Regc.Oci.{Descriptor, Error, Options, Reference}
alias Regc.Oci.Manifest.{Decoder, Fetcher, Verifier}
alias Regc.Oci.Manifest.Decoder.Result
@enforce_keys [:kind, :descriptor, :raw, :document, :reference]
defstruct [
:kind,
:descriptor,
:raw,
:document,
:reference,
:config,
layers: [],
manifests: [],
headers: %{}
]
@type t :: %__MODULE__{
kind: :index | :image,
descriptor: Descriptor.t(),
raw: binary(),
document: map(),
reference: Reference.t(),
config: Descriptor.t() | nil,
layers: [Descriptor.t()],
manifests: [Descriptor.t()],
headers: map()
}
@doc false
@spec fetch(Reference.t(), keyword() | Options.t(), Descriptor.t() | nil) ::
{:ok, t()} | {:error, Error.t()}
def fetch(reference, opts, expected \\ nil)
def fetch(%Reference{} = reference, opts, expected) when is_list(opts) do
case Options.parse(opts) do
{:ok, options} ->
fetch(reference, options, expected)
{:error, {:invalid_option, option} = cause} ->
Error.result(
:manifest_fetch,
:invalid_option,
"#{option} is invalid",
reference: reference,
cause: cause
)
end
end
def fetch(%Reference{} = reference, %Options{} = options, expected) do
case Options.validate(options) do
{:ok, options} ->
fetch_with_options(reference, options, expected)
{:error, {:invalid_option, option} = cause} ->
option_error(option, cause, reference)
end
end
@doc false
@spec fetch_with_options(Reference.t(), Options.t(), Descriptor.t() | nil) ::
{:ok, t()} | {:error, Error.t()}
def fetch_with_options(%Reference{} = reference, %Options{} = options, expected \\ nil) do
with {:ok, response} <- Fetcher.fetch(reference, options, expected),
:ok <- Verifier.verify(response, reference, expected),
{:ok, %Result{} = result} <-
Decoder.decode(
response,
reference,
expected,
options,
options.max_manifest_bytes
) do
{:ok, struct!(__MODULE__, Map.from_struct(result))}
end
end
defp option_error(option, cause, reference) do
Error.result(
:manifest_fetch,
:invalid_option,
Options.error_message(option),
reference: reference,
cause: cause
)
end
end