Implement class data source

This commit is contained in:
nora 2024-04-21 13:30:25 +02:00
parent 85d10ed893
commit 3c891034ee
7 changed files with 144 additions and 19 deletions

View file

@ -1,5 +1,8 @@
use eyre::{Context, OptionExt, Result};
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::{
header::{HeaderMap, HeaderValue},
RequestBuilder, Response,
};
#[derive(Clone)]
pub struct CorsClient {
@ -29,7 +32,7 @@ impl CorsClient {
let mut headers = HeaderMap::new();
headers.insert(
"Authorization",
HeaderValue::from_str(&format!("Bearer {}", token,)).unwrap(),
HeaderValue::from_str(token).unwrap(),
);
let client = reqwest::Client::builder()
.default_headers(headers)
@ -40,12 +43,27 @@ impl CorsClient {
}
pub async fn get_hugo(&self) -> Result<String> {
Ok(self
.client
.get(format!("{URL}/hugo"))
.send()
Ok(do_request(self.client.get(format!("{URL}/hugo")))
.await?
.text()
.await?)
}
pub async fn get_class(&self, id: &str) -> Result<dto::Class> {
Ok(do_request(self.client.get(format!("{URL}/classes/{id}")))
.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);
}
Ok(res.error_for_status().wrap_err("failed to get class")?)
}

View file

@ -48,6 +48,7 @@ impl Provider for ExampleProvider {
vec![
resources::kitty::ExampleDataSource::erase(),
resources::hugo::HugoDataSource::erase(),
resources::class_data_source::ClassDataSource::erase(),
]
}
}

View file

@ -0,0 +1,92 @@
use std::collections::HashMap;
use eyre::Context;
use terustform::{
datasource::DataSource, AttrPath, Attribute, DResult, EyreExt, Mode, Schema, StringValue,
Value, ValueModel,
};
use crate::client::CorsClient;
pub struct ClassDataSource {
client: CorsClient,
}
#[derive(terustform::Model)]
struct ClassDataSourceModel {
id: StringValue,
name: StringValue,
description: StringValue,
discord_id: StringValue,
}
#[terustform::async_trait]
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 class = self
.client
.get_class(&model.id.expect_known(AttrPath::attr("id"))?)
.await
.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())
}
fn name(provider_name: &str) -> String {
format!("{provider_name}_class")
}
fn schema() -> Schema {
Schema {
description: "Get a class by name".to_owned(),
attributes: HashMap::from([
(
"id".to_owned(),
// TODO: UUID validation :3
Attribute::String {
description: "The UUID".to_owned(),
mode: Mode::Required,
sensitive: false,
},
),
(
"name".to_owned(),
Attribute::String {
description: "The description".to_owned(),
mode: Mode::Computed,
sensitive: false,
},
),
(
"description".to_owned(),
Attribute::String {
description: "The description".to_owned(),
mode: Mode::Computed,
sensitive: false,
},
),
(
"discord_id".to_owned(),
Attribute::String {
description: "The discord ID of the class".to_owned(),
mode: Mode::Computed,
sensitive: false,
},
),
]),
}
}
fn new(data: Self::ProviderData) -> DResult<Self> {
Ok(Self { client: data })
}
}

View file

@ -35,17 +35,11 @@ impl DataSource for HugoDataSource {
.to_value())
}
fn name(provider_name: &str) -> String
where
Self: Sized,
{
fn name(provider_name: &str) -> String {
format!("{provider_name}_hugo")
}
fn schema() -> Schema
where
Self: Sized,
{
fn schema() -> Schema {
Schema {
description: "Get Hugo Boss".to_owned(),
attributes: HashMap::from([(
@ -59,10 +53,7 @@ impl DataSource for HugoDataSource {
}
}
fn new(data: Self::ProviderData) -> DResult<Self>
where
Self: Sized,
{
fn new(data: Self::ProviderData) -> DResult<Self> {
Ok(Self { client: data })
}
}

View file

@ -1,2 +1,3 @@
pub mod class_data_source;
pub mod hugo;
pub mod kitty;
pub mod kitty;

View file

@ -26,4 +26,11 @@ output "cat2" {
data "corsschool_hugo" "hugo" {}
output "hugo" {
value = data.corsschool_hugo.hugo
}
data "corsschool_class" "test" {
id = "f245514b-f99c-4c09-ab53-eabd944af6d2"
}
output "class" {
value = data.corsschool_class.test
}

View file

@ -146,6 +146,21 @@ impl<T> BaseValue<T> {
}
}
impl<T> From<T> for BaseValue<T> {
fn from(value: T) -> Self {
Self::Known(value)
}
}
impl<T> From<Option<T>> for BaseValue<T> {
fn from(value: Option<T>) -> Self {
match value {
Some(value) => Self::Known(value),
None => Self::Null,
}
}
}
pub trait ValueModel: Sized {
fn from_value(v: Value, path: &AttrPath) -> DResult<Self>;