containerd_shimkit/sandbox/
error.rs1use anyhow::Error as AnyError;
5use containerd_shim::Error as ShimError;
6use containerd_shim::protos::ttrpc;
7use oci_spec::OciSpecError;
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum Error {
12 #[error("{0}")]
14 Oci(#[from] OciSpecError),
15 #[error("{0}")]
17 Stdio(#[from] std::io::Error),
18 #[error("{0}")]
19 Others(String),
20 #[error("{0}")]
22 Shim(#[from] ShimError),
23 #[error("not found: {0}")]
25 NotFound(String),
26 #[error("already exists: {0}")]
28 AlreadyExists(String),
29 #[error("invalid argument: {0}")]
31 InvalidArgument(String),
32 #[error("{0}")]
34 Any(#[from] AnyError),
35 #[error("{0}")]
37 FailedPrecondition(String),
38 #[error("{0}")]
40 Json(#[from] serde_json::Error),
41 #[cfg(unix)]
43 #[error("{0}")]
44 Errno(#[from] nix::errno::Errno),
45 #[cfg(unix)]
47 #[error("{0}")]
48 Libcontainer(#[from] libcontainer::error::LibcontainerError),
49 #[error("{0}")]
50 Containerd(String),
51}
52
53pub type Result<T, E = Error> = ::std::result::Result<T, E>;
54
55impl From<Error> for ttrpc::Error {
56 fn from(e: Error) -> Self {
57 match e {
58 Error::Shim(ref s) => match s {
59 ShimError::InvalidArgument(s) => {
60 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::INVALID_ARGUMENT, s))
61 }
62 ShimError::NotFoundError(s) => {
63 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::NOT_FOUND, s))
64 }
65 _ => ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::UNKNOWN, s)),
66 },
67 Error::NotFound(ref s) => {
68 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::NOT_FOUND, s))
69 }
70 Error::AlreadyExists(ref s) => {
71 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::ALREADY_EXISTS, s))
72 }
73 Error::InvalidArgument(ref s) => {
74 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::INVALID_ARGUMENT, s))
75 }
76 Error::FailedPrecondition(ref s) => {
77 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::FAILED_PRECONDITION, s))
78 }
79 Error::Oci(ref _s) => {
80 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::UNKNOWN, e.to_string()))
81 }
82 Error::Any(ref s) => {
83 ttrpc::Error::RpcStatus(ttrpc::get_status(ttrpc::Code::UNKNOWN, s))
84 }
85 _ => ttrpc::Error::Others(e.to_string()),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use thiserror::Error;
93
94 use super::*;
95
96 #[derive(Debug, Error)]
97 enum TestError {
98 #[error("{0}")]
99 AnError(String),
100 }
101
102 #[test]
103 fn test_error_to_ttrpc_status() {
104 let e = Error::InvalidArgument("invalid argument".to_string());
105 let t: ttrpc::Error = e.into();
106 match t {
107 ttrpc::Error::RpcStatus(s) => {
108 assert_eq!(s.code(), ttrpc::Code::INVALID_ARGUMENT);
109 assert_eq!(s.message, "invalid argument");
110 }
111 _ => panic!("unexpected error"),
112 }
113
114 let e = Error::NotFound("not found".to_string());
115 let t: ttrpc::Error = e.into();
116 match t {
117 ttrpc::Error::RpcStatus(s) => {
118 assert_eq!(s.code(), ttrpc::Code::NOT_FOUND);
119 assert_eq!(s.message, "not found");
120 }
121 _ => panic!("unexpected error"),
122 }
123
124 let e = Error::AlreadyExists("already exists".to_string());
125 let t: ttrpc::Error = e.into();
126 match t {
127 ttrpc::Error::RpcStatus(s) => {
128 assert_eq!(s.code(), ttrpc::Code::ALREADY_EXISTS);
129 assert_eq!(s.message, "already exists");
130 }
131 _ => panic!("unexpected error"),
132 }
133
134 let e = Error::FailedPrecondition("failed precondition".to_string());
135 let t: ttrpc::Error = e.into();
136 match t {
137 ttrpc::Error::RpcStatus(s) => {
138 assert_eq!(s.code(), ttrpc::Code::FAILED_PRECONDITION);
139 assert_eq!(s.message, "failed precondition");
140 }
141 _ => panic!("unexpected error"),
142 }
143
144 let e = Error::Shim(ShimError::InvalidArgument("invalid argument".to_string()));
145 let t: ttrpc::Error = e.into();
146 match t {
147 ttrpc::Error::RpcStatus(s) => {
148 assert_eq!(s.code(), ttrpc::Code::INVALID_ARGUMENT);
149 assert_eq!(s.message, "invalid argument");
150 }
151 _ => panic!("unexpected error"),
152 }
153
154 let e = Error::Any(AnyError::new(TestError::AnError("any error".to_string())));
155 let t: ttrpc::Error = e.into();
156 match t {
157 ttrpc::Error::RpcStatus(s) => {
158 assert_eq!(s.code(), ttrpc::Code::UNKNOWN);
159 assert_eq!(s.message, "any error");
160 }
161 _ => panic!("unexpected error"),
162 }
163 }
164}