Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ serde = { version = "1.0.129", features = ["derive"] }
thiserror = "2.0.0"
serde_json = "1.0.66"
quickcheck = { version = "1.0.3", optional = true }
derive_builder = "0.20.0"
bon = "3"
getset = "0.1.3"
strum = "0.27.0"
strum_macros = "0.27.0"
Expand Down
25 changes: 10 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,18 @@ assert_eq!(image_manifest.layers().len(), 5);
```rust no_run
use std::str::FromStr;
use oci_spec::image::{
Descriptor,
DescriptorBuilder,
ImageManifest,
ImageManifestBuilder,
Descriptor,
ImageManifest,
MediaType,
Sha256Digest,
SCHEMA_VERSION
};

let config = DescriptorBuilder::default()
let config = Descriptor::builder()
.media_type(MediaType::ImageConfig)
.size(7023u64)
.digest(Sha256Digest::from_str("b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7").unwrap())
.build()
.expect("build config descriptor");
.build();

let layers: Vec<Descriptor> = [
(
Expand All @@ -72,21 +69,19 @@ let layers: Vec<Descriptor> = [
]
.iter()
.map(|l| {
DescriptorBuilder::default()
Descriptor::builder()
.media_type(MediaType::ImageLayerGzip)
.size(l.0)
.digest(Sha256Digest::from_str(l.1).unwrap())
.build()
.expect("build layer")
})
.collect();

let image_manifest = ImageManifestBuilder::default()
let image_manifest = ImageManifest::builder()
.schema_version(SCHEMA_VERSION)
.config(config)
.layers(layers)
.build()
.expect("build image manifest");
.build();

image_manifest.to_file_pretty("my-manifest.json").unwrap();
```
Expand Down Expand Up @@ -123,11 +118,11 @@ image_manifest.to_file_pretty("my-manifest.json").unwrap();
## Distribution Spec Examples
- Create a list of repositories
```rust
use oci_spec::distribution::RepositoryListBuilder;
use oci_spec::distribution::RepositoryList;

let list = RepositoryListBuilder::default()
let list = RepositoryList::builder()
.repositories(vec!["busybox".to_owned()])
.build().unwrap();
.build();
```

# Contributing
Expand Down
60 changes: 15 additions & 45 deletions src/distribution/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Error types of the distribution spec.

use crate::error::OciSpecError;
use derive_builder::Builder;
use bon::Builder;
use getset::Getters;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display, Formatter};
Expand Down Expand Up @@ -48,11 +47,7 @@ pub enum ErrorCode {
}

#[derive(Builder, Clone, Debug, Deserialize, Eq, Error, Getters, PartialEq, Serialize)]
#[builder(
pattern = "owned",
setter(into, strip_option),
build_fn(error = "OciSpecError")
)]
#[builder(on(_, into))]
#[getset(get = "pub")]
/// ErrorResponse is returned by a registry on an invalid request.
pub struct ErrorResponse {
Expand All @@ -74,11 +69,7 @@ impl ErrorResponse {
}

#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)]
#[builder(
pattern = "owned",
setter(into, strip_option),
build_fn(error = "OciSpecError")
)]
#[builder(on(_, into))]
#[getset(get = "pub")]
/// Describes a server error returned from a registry.
pub struct ErrorInfo {
Expand All @@ -87,13 +78,11 @@ pub struct ErrorInfo {
code: ErrorCode,

#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(default = "None")]
/// The message field is OPTIONAL, and if present, it SHOULD be a human readable string or
/// MAY be empty.
message: Option<String>,

#[serde(default, skip_serializing_if = "Option::is_none", with = "json_string")]
#[builder(default = "None")]
/// The detail field is OPTIONAL and MAY contain arbitrary JSON data providing information
/// the client can use to resolve the issue.
detail: Option<String>,
Expand Down Expand Up @@ -142,61 +131,44 @@ mod json_string {
#[cfg(test)]
mod tests {
use super::*;
use crate::error::Result;

#[test]
fn error_response_success() -> Result<()> {
let response = ErrorResponseBuilder::default().errors(vec![]).build()?;
fn error_response_success() {
let response = ErrorResponse::builder().errors(vec![]).build();
assert!(response.detail().is_empty());
assert_eq!(response.to_string(), ERR_REGISTRY);
Ok(())
}

#[test]
fn error_response_failure() {
assert!(ErrorResponseBuilder::default().build().is_err());
}

#[test]
fn error_info_success() -> Result<()> {
let info = ErrorInfoBuilder::default()
.code(ErrorCode::BlobUnknown)
.build()?;
fn error_info_success() {
let info = ErrorInfo::builder().code(ErrorCode::BlobUnknown).build();
assert_eq!(info.code(), &ErrorCode::BlobUnknown);
assert!(info.message().is_none());
assert!(info.detail().is_none());
Ok(())
}

#[test]
fn error_info_failure() {
assert!(ErrorInfoBuilder::default().build().is_err());
}

#[test]
fn error_info_serialize_success() -> Result<()> {
let error_info = ErrorInfoBuilder::default()
fn error_info_serialize_success() {
let error_info = ErrorInfo::builder()
.code(ErrorCode::Unauthorized)
.detail(String::from("{ \"key\": \"value\" }"))
.build()?;
.build();

assert!(serde_json::to_string(&error_info).is_ok());
Ok(())
}

#[test]
fn error_info_serialize_failure() -> Result<()> {
let error_info = ErrorInfoBuilder::default()
fn error_info_serialize_failure() {
let error_info = ErrorInfo::builder()
.code(ErrorCode::Unauthorized)
.detail(String::from("abcd"))
.build()?;
.build();

assert!(serde_json::to_string(&error_info).is_err());
Ok(())
}

#[test]
fn error_info_deserialize_success() -> Result<()> {
fn error_info_deserialize_success() {
let error_info_str = r#"
{
"code": "MANIFEST_UNKNOWN",
Expand All @@ -206,9 +178,7 @@ mod tests {
}
}"#;

let error_info: ErrorInfo = serde_json::from_str(error_info_str)?;
let error_info: ErrorInfo = serde_json::from_str(error_info_str).unwrap();
assert_eq!(error_info.detail().as_ref().unwrap(), "{\"Tag\":\"lates\"}");

Ok(())
}
}
22 changes: 4 additions & 18 deletions src/distribution/repository.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
//! Repository types of the distribution spec.

use crate::error::OciSpecError;
use derive_builder::Builder;
use bon::Builder;
use getset::{Getters, Setters};
use serde::{Deserialize, Serialize};

#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, Setters, PartialEq, Serialize)]
#[builder(
pattern = "owned",
setter(into, strip_option),
build_fn(error = "OciSpecError")
)]
#[builder(on(_, into))]
#[getset(get = "pub", set = "pub")]
/// RepositoryList returns a catalog of repositories maintained on the registry.
pub struct RepositoryList {
Expand All @@ -21,19 +16,10 @@ pub struct RepositoryList {
#[cfg(test)]
mod tests {
use super::*;
use crate::error::Result;

#[test]
fn repository_list_success() -> Result<()> {
let list = RepositoryListBuilder::default()
.repositories(vec![])
.build()?;
fn repository_list_success() {
let list = RepositoryList::builder().repositories(vec![]).build();
assert!(list.repositories().is_empty());
Ok(())
}

#[test]
fn repository_list_failure() {
assert!(RepositoryListBuilder::default().build().is_err());
}
}
23 changes: 4 additions & 19 deletions src/distribution/tag.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
//! Tag types of the distribution spec.

use crate::error::OciSpecError;
use derive_builder::Builder;
use bon::Builder;
use getset::{Getters, Setters};
use serde::{Deserialize, Serialize};

#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, Setters, PartialEq, Serialize)]
#[builder(
pattern = "owned",
setter(into, strip_option),
build_fn(error = "OciSpecError")
)]
#[builder(on(_, into))]
#[getset(get = "pub", set = "pub")]
/// A list of tags for a given repository.
pub struct TagList {
Expand All @@ -24,21 +19,11 @@ pub struct TagList {
#[cfg(test)]
mod tests {
use super::*;
use crate::error::Result;

#[test]
fn tag_list_success() -> Result<()> {
let list = TagListBuilder::default()
.name("name")
.tags(vec![])
.build()?;
fn tag_list_success() {
let list = TagList::builder().name("name").tags(vec![]).build();
assert!(list.tags().is_empty());
assert_eq!(list.name(), "name");
Ok(())
}

#[test]
fn tag_list_failure() {
assert!(TagListBuilder::default().build().is_err());
}
}
4 changes: 0 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ pub enum OciSpecError {
/// serialization or deserialization.
#[error("serde failed")]
SerDe(#[from] serde_json::Error),

/// Builder specific errors.
#[error("uninitialized field")]
Builder(#[from] derive_builder::UninitializedFieldError),
}

pub(crate) fn oci_error<'a, M>(message: M) -> OciSpecError
Expand Down
Loading
Loading