Continue implementing resources

This commit is contained in:
nora 2024-04-29 21:24:03 +02:00
parent bf7bd330b3
commit f46d9b299d
13 changed files with 309 additions and 106 deletions

View file

@ -11,3 +11,4 @@ terustform = { path = "../terustform" }
tokio = { version = "1.37.0", features = ["full"] }
dto = { git = "https://github.com/nilstrieb-lehre/davinci-cors.git", rev = "bef75a802cf48cf63d171136c2cea67b83055387" }
serde = "1.0.199"

View file

@ -30,10 +30,7 @@ impl CorsClient {
.wrap_err("Token is invalid utf8")?;
let mut headers = HeaderMap::new();
headers.insert(
"Authorization",
HeaderValue::from_str(token).unwrap(),
);
headers.insert("Authorization", HeaderValue::from_str(token).unwrap());
let client = reqwest::Client::builder()
.default_headers(headers)
.build()
@ -46,24 +43,37 @@ impl CorsClient {
Ok(do_request(self.client.get(format!("{URL}/hugo")))
.await?
.text()
.await?)
.await
.wrap_err("failed to get hugo")?)
}
pub async fn get_class(&self, id: &str) -> Result<dto::Class> {
Ok(do_request(self.client.get(format!("{URL}/classes/{id}")))
.await?
.json()
.await?)
Ok(
do_request_body(self.client.get(format!("{URL}/classes/{id}")))
.await
.wrap_err("failed to get class")?,
)
}
pub async fn post_class(&self, class: &dto::Class) -> Result<dto::Class> {
Ok(
do_request_body(self.client.post(format!("{URL}/classes")).json(class))
.await
.wrap_err("creating class")?,
)
}
}
async fn do_request_body<T: serde::de::DeserializeOwned>(req: RequestBuilder) -> Result<T> {
Ok(do_request(req).await?.json().await?)
}
async fn do_request(req: RequestBuilder) -> Result<Response> {
dbg!(&req);
let res = req.send().await?;
if let Err(err) = res.error_for_status_ref() {
let text = res.text().await.unwrap_or_default();
return Err(err).wrap_err(text);
}
res.error_for_status().wrap_err("failed to get class")
res.error_for_status().wrap_err("failed make request")
}

View file

@ -13,18 +13,18 @@ pub struct ClassDataSource {
}
#[derive(terustform::Model)]
struct ClassDataSourceModel {
id: StringValue,
name: StringValue,
description: StringValue,
discord_id: StringValue,
pub(super) struct ClassModel {
pub(super) id: StringValue,
pub(super) name: StringValue,
pub(super) description: StringValue,
pub(super) discord_id: StringValue,
}
impl DataSource for ClassDataSource {
type ProviderData = CorsClient;
async fn read(&self, config: Value) -> DResult<Value> {
let mut model = ClassDataSourceModel::from_value(config, &AttrPath::root())?;
let model = ClassModel::from_value(config, &AttrPath::root())?;
let class = self
.client
@ -33,11 +33,13 @@ impl DataSource for ClassDataSource {
.wrap_err("failed to get class")
.eyre_to_tf()?;
model.name = StringValue::Known(class.name);
model.description = StringValue::Known(class.description);
model.discord_id = StringValue::from(class.discord_id);
Ok(model.to_value())
Ok(ClassModel {
id: model.id,
name: class.name.into(),
description: class.description.into(),
discord_id: class.discord_id.into(),
}
.to_value())
}
fn name(provider_name: &str) -> String {

View file

@ -1,9 +1,13 @@
use std::collections::HashMap;
use terustform::{resource::Resource, Attribute, DResult, Mode, Schema, Value};
use terustform::{
resource::Resource, AttrPath, Attribute, DResult, EyreExt, Mode, Schema, Value, ValueModel,
};
use crate::client::CorsClient;
use super::class_data_source::ClassModel;
pub struct ClassResource {
client: CorsClient,
}
@ -11,19 +15,59 @@ pub struct ClassResource {
impl Resource for ClassResource {
type ProviderData = CorsClient;
async fn read(&self, config: Value) -> DResult<Value> {
async fn read(&self, current_state: Value) -> DResult<Value> {
let model = ClassModel::from_value(current_state, &AttrPath::root())?;
let class = self
.client
.get_class(model.id.expect_known(AttrPath::attr("id"))?)
.await
.eyre_to_tf()?;
Ok(ClassModel {
id: model.id,
name: class.name.into(),
description: class.description.into(),
discord_id: class.discord_id.into(),
}
.to_value())
}
async fn create(&self, _config: Value, plan: Value) -> DResult<Value> {
let model = ClassModel::from_root_value(plan)?;
let class = self
.client
.post_class(&dto::Class {
id: Default::default(),
members: vec![],
name: model.name.expect_known(AttrPath::attr("name"))?.clone(),
description: model
.description
.expect_known(AttrPath::attr("description"))?
.clone(),
discord_id: model
.discord_id
.expect_known_or_null(AttrPath::attr("discord_id"))?
.cloned(),
})
.await
.eyre_to_tf()?;
Ok(ClassModel {
id: class.id.to_string().into(),
name: class.name.into(),
description: class.description.into(),
discord_id: class.discord_id.into(),
}
.to_value())
}
async fn update(&self, _config: Value, _plan: Value, _state: Value) -> DResult<Value> {
todo!()
}
async fn create(&self, config: Value) -> DResult<Value> {
todo!()
}
async fn update(&self, config: Value) -> DResult<Value> {
todo!()
}
async fn delete(&self, state: Value) -> DResult<Value> {
async fn delete(&self, _state: Value) -> DResult<Value> {
todo!()
}
@ -56,7 +100,7 @@ impl Resource for ClassResource {
"description".to_owned(),
Attribute::String {
description: "The description".to_owned(),
mode: Mode::Optional,
mode: Mode::Required,
sensitive: false,
},
),

View file

@ -22,4 +22,5 @@ output "class" {
resource "corsschool_class" "myclass" {
name = "meow"
description = "???"
}