incus_client/resources/
projects.rs1use serde::Deserialize;
4
5use crate::error::{Error, Result};
6use crate::transport::{
7 resource_error_or, sync_metadata, Client, Method, RecursionQuery, WithEtag,
8};
9
10#[derive(Debug, Clone, Deserialize)]
11pub struct Project {
12 pub name: String,
13 #[serde(default)]
14 pub description: String,
15 #[serde(default)]
16 pub config: serde_json::Value,
17}
18
19impl Client {
20 pub async fn list_projects(&self, recursion: bool) -> Result<Vec<serde_json::Value>> {
21 let recursion_query = RecursionQuery::new(recursion);
22 let envelope = self
23 .request(
24 Method::Get,
25 "/1.0/projects",
26 &recursion_query.as_query(),
27 None,
28 None,
29 )
30 .await?;
31 Ok(serde_json::from_value(sync_metadata(envelope, "list")?)?)
32 }
33
34 pub async fn get_project(&self, name: &str) -> Result<WithEtag<Project>> {
37 let path = format!("/1.0/projects/{name}");
38 let envelope = self
39 .request(Method::Get, &path, &[], None, None)
40 .await
41 .map_err(|err| resource_error_or(err, name))?;
42 match envelope {
43 crate::transport::IncusEnvelope::Sync { metadata, etag } => Ok(WithEtag {
44 value: serde_json::from_value(metadata)?,
45 etag,
46 }),
47 other => Err(Error::InvalidResponse(format!(
48 "expected a sync project response, got {other:?}"
49 ))),
50 }
51 }
52
53 pub async fn create_project(&self, params: &serde_json::Value) -> Result<()> {
58 self.request(Method::Post, "/1.0/projects", &[], Some(params), None)
59 .await?;
60 Ok(())
61 }
62
63 pub async fn update_project(
71 &self,
72 name: &str,
73 new_definition: &serde_json::Value,
74 etag: Option<&str>,
75 ) -> Result<()> {
76 let path = format!("/1.0/projects/{name}");
77 self.request(Method::Put, &path, &[], Some(new_definition), etag)
78 .await
79 .map_err(|err| resource_error_or(err, name))?;
80 Ok(())
81 }
82
83 pub async fn update_project_guarded(
88 &self,
89 fetched: &WithEtag<Project>,
90 new_definition: &serde_json::Value,
91 ) -> Result<()> {
92 self.update_project(&fetched.value().name, new_definition, fetched.etag())
93 .await
94 }
95
96 pub async fn delete_project(&self, name: &str) -> Result<()> {
99 let path = format!("/1.0/projects/{name}");
100 self.request(Method::Delete, &path, &[], None, None)
101 .await
102 .map_err(|err| resource_error_or(err, name))?;
103 Ok(())
104 }
105}
106
107#[cfg(test)]
108#[path = "projects_tests.rs"]
109mod tests;