OCI.Storage.Adapter behaviour (oci v0.0.6)

View Source

Behaviour for OCI registry storage backends.

This module defines the interface that storage adapters must implement to work with OCI (Open Container Initiative) registries. A storage adapter is responsible for storing and retrieving container images and their components.

Key Concepts

  • Repository: A collection of related container images (e.g., "myapp/backend")
  • Blob: Binary data that represents layers of a container image or configuration
  • Manifest: A JSON document that describes a container image, including its layers and configuration
  • Digest: A unique identifier for a blob, typically a SHA-256 hash
  • Reference: A human-readable identifier for a manifest (e.g., "latest", "v1.0.0")

Implementation Guide

When implementing this behaviour, you'll need to handle:

  1. Repository initialization and management
  2. Blob storage and retrieval
  3. Manifest storage and retrieval
  4. Tag management
  5. Upload handling for large blobs

Example Usage

defmodule MyStorageAdapter do
  @behaviour OCI.Storage.Adapter

  defstruct [:path]  # Define your struct fields here

  # Implement all callbacks here
end

Summary

Callbacks

Checks if a blob exists in the repository and returns its size if found.

Cancels an ongoing blob upload session.

Finalizes a blob upload and verifies the digest.

Deletes a blob from the repository.

Deletes a manifest from the repository.

Retrieves a blob's content from the repository.

Gets the total size of an ongoing blob upload.

Gets the status of an ongoing blob upload.

Retrieves a manifest from the repository.

Initializes a new storage adapter instance with the given configuration.

Initiates a blob upload session.

Lists tags in a repository with pagination support.

Gets metadata about a manifest without retrieving its content.

Mounts a blob from one repository to another.

Checks if a repository exists.

Uploads a chunk of data to an ongoing blob upload.

Checks if an upload exists.

Types

error_details_t()

@type error_details_t() :: any()

t()

@type t() :: struct()

Callbacks

blob_exists?(storage, repo, digest, ctx)

@callback blob_exists?(
  storage :: t(),
  repo :: String.t(),
  digest :: String.t(),
  ctx :: OCI.Context.t()
) :: boolean()

Checks if a blob exists in the repository and returns its size if found.

cancel_blob_upload(storage, repo, uuid, ctx)

@callback cancel_blob_upload(
  storage :: t(),
  repo :: String.t(),
  uuid :: String.t(),
  ctx :: OCI.Context.t()
) ::
  :ok
  | {:error, :BLOB_UPLOAD_UNKNOWN}
  | {:error, :BLOB_UPLOAD_UNKNOWN, error_details_t()}

Cancels an ongoing blob upload session.

complete_blob_upload(storage, repo, upload_id, digest, ctx)

@callback complete_blob_upload(
  storage :: t(),
  repo :: String.t(),
  upload_id :: String.t(),
  digest :: String.t(),
  ctx :: OCI.Context.t()
) :: :ok | {:error, atom()} | {:error, atom(), error_details_t()}

Finalizes a blob upload and verifies the digest.

delete_blob(storage, repo, digest, ctx)

@callback delete_blob(
  storage :: t(),
  repo :: String.t(),
  digest :: String.t(),
  ctx :: OCI.Context.t()
) :: :ok | {:error, :BLOB_UNKNOWN} | {:error, :BLOB_UNKNOWN, error_details_t()}

Deletes a blob from the repository.

delete_manifest(storage, repo, reference, ctx)

@callback delete_manifest(
  storage :: t(),
  repo :: String.t(),
  reference :: String.t(),
  ctx :: OCI.Context.t()
) :: :ok | {:error, atom()}

Deletes a manifest from the repository.

get_blob(storage, repo, digest, ctx)

@callback get_blob(
  storage :: t(),
  repo :: String.t(),
  digest :: String.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, content :: binary()}
  | {:error, :BLOB_UNKNOWN}
  | {:error, :BLOB_UNKNOWN, error_details_t()}

Retrieves a blob's content from the repository.

get_blob_upload_offset(storage, repo, uuid, ctx)

@callback get_blob_upload_offset(
  storage :: t(),
  repo :: String.t(),
  uuid :: String.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, size :: non_neg_integer()}
  | {:error, term()}
  | {:error, term(), error_details_t()}

Gets the total size of an ongoing blob upload.

get_blob_upload_status(storage, repo, uuid, ctx)

@callback get_blob_upload_status(
  storage :: t(),
  repo :: String.t(),
  uuid :: String.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, range :: String.t()}
  | {:error, term()}
  | {:error, term(), error_details_t()}

Gets the status of an ongoing blob upload.

get_manifest(storage, repo, reference, ctx)

@callback get_manifest(
  storage :: t(),
  repo :: String.t(),
  reference :: String.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, manifest :: binary(), content_type :: String.t()}
  | {:error, atom(), error_details_t()}

Retrieves a manifest from the repository.

init(config)

@callback init(config :: map()) ::
  {:ok, storage :: t()} | {:error, term()} | {:error, term(), error_details_t()}

Initializes a new storage adapter instance with the given configuration.

initiate_blob_upload(storage, repo, ctx)

@callback initiate_blob_upload(storage :: t(), repo :: String.t(), ctx :: OCI.Context.t()) ::
  {:ok, upload_id :: String.t()}
  | {:error, term()}
  | {:error, term(), error_details_t()}

Initiates a blob upload session.

list_tags(storage, repo, pagination, ctx)

@callback list_tags(
  storage :: t(),
  repo :: String.t(),
  pagination :: OCI.Pagination.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, tags :: [String.t()]}
  | {:error, :NAME_UNKNOWN}
  | {:error, :NAME_UNKNOWN, error_details_t()}

Lists tags in a repository with pagination support.

manifest_exists?(storage, repo, reference, ctx)

@callback manifest_exists?(
  storage :: t(),
  repo :: String.t(),
  reference :: String.t(),
  ctx :: OCI.Context.t()
) :: boolean()

Gets metadata about a manifest without retrieving its content.

mount_blob(storage, repo, digest, from_repo, ctx)

@callback mount_blob(
  storage :: t(),
  repo :: String.t(),
  digest :: String.t(),
  from_repo :: String.t(),
  ctx :: OCI.Context.t()
) :: :ok | {:error, :BLOB_UNKNOWN} | {:error, :BLOB_UNKNOWN, error_details_t()}

Mounts a blob from one repository to another.

repo_exists?(storage, repo, ctx)

@callback repo_exists?(storage :: t(), repo :: String.t(), ctx :: OCI.Context.t()) ::
  boolean()

Checks if a repository exists.

store_manifest(storage, repo, reference, manifest, manifest_digest, ctx)

@callback store_manifest(
  storage :: t(),
  repo :: String.t(),
  reference :: String.t(),
  manifest :: map(),
  manifest_digest :: String.t(),
  ctx :: OCI.Context.t()
) ::
  :ok
  | {:error, :MANIFEST_BLOB_UNKNOWN | :MANIFEST_INVALID | :NAME_UNKNOWN,
     error_details_t()}

Stores a manifest in the repository.

upload_blob_chunk(storage, repo, uuid, chunk, content_range, ctx)

@callback upload_blob_chunk(
  storage :: t(),
  repo :: String.t(),
  uuid :: String.t(),
  chunk :: binary(),
  content_range :: String.t(),
  ctx :: OCI.Context.t()
) ::
  {:ok, range :: String.t()}
  | {:error, atom()}
  | {:error, atom(), error_details_t()}

Uploads a chunk of data to an ongoing blob upload.

upload_exists?(storage, repo, uuid, ctx)

@callback upload_exists?(
  storage :: t(),
  repo :: String.t(),
  uuid :: String.t(),
  ctx :: OCI.Context.t()
) :: boolean()

Checks if an upload exists.