mirror of
https://github.com/Noratrieb/terustform.git
synced 2026-01-14 08:30:13 +01:00
Improvements
This commit is contained in:
parent
edf7b7dac3
commit
bf7bd330b3
10 changed files with 189 additions and 72 deletions
34
Cargo.lock
generated
34
Cargo.lock
generated
|
|
@ -650,6 +650,15 @@ version = "0.4.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
|
|
@ -990,8 +999,17 @@ checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
|||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
"regex-automata 0.4.6",
|
||||
"regex-syntax 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax 0.6.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1002,9 +1020,15 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
|||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"regex-syntax 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
|
|
@ -1590,10 +1614,14 @@ version = "0.3.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ mod resources;
|
|||
use std::collections::HashMap;
|
||||
|
||||
use eyre::Context;
|
||||
use terustform::{datasource::DataSource, provider::Provider, DResult, EyreExt, Schema, Value};
|
||||
use terustform::{
|
||||
datasource::DataSource, provider::Provider, resource::Resource, DResult, EyreExt, Schema, Value,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
|
|
@ -49,6 +51,6 @@ impl Provider for ExampleProvider {
|
|||
}
|
||||
|
||||
fn resources(&self) -> terustform::provider::Resources<Self> {
|
||||
vec![]
|
||||
vec![resources::class_resource::ClassResource::erase()]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,78 @@
|
|||
use terustform::{datasource::DataSource, DResult, Value};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use terustform::{resource::Resource, Attribute, DResult, Mode, Schema, Value};
|
||||
|
||||
use crate::client::CorsClient;
|
||||
|
||||
pub struct ClassResource {
|
||||
client: CorsClient,
|
||||
}
|
||||
|
||||
impl Resource for ClassResource {
|
||||
type ProviderData = CorsClient;
|
||||
|
||||
async fn read(&self, config: 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> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn name(provider_name: &str) -> String {
|
||||
format!("{provider_name}_class")
|
||||
}
|
||||
|
||||
fn schema() -> terustform::Schema {
|
||||
Schema {
|
||||
description: "A class".into(),
|
||||
attributes: HashMap::from([
|
||||
(
|
||||
"id".to_owned(),
|
||||
// TODO: UUID validation :3
|
||||
Attribute::String {
|
||||
description: "The UUID".to_owned(),
|
||||
mode: Mode::Computed,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"name".to_owned(),
|
||||
Attribute::String {
|
||||
description: "The description".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"description".to_owned(),
|
||||
Attribute::String {
|
||||
description: "The description".to_owned(),
|
||||
mode: Mode::Optional,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"discord_id".to_owned(),
|
||||
Attribute::String {
|
||||
description: "The discord ID of the class".to_owned(),
|
||||
mode: Mode::Optional,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
fn new(client: Self::ProviderData) -> DResult<Self> {
|
||||
Ok(Self { client })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,4 +18,8 @@ data "corsschool_class" "test" {
|
|||
}
|
||||
output "class" {
|
||||
value = data.corsschool_class.test
|
||||
}
|
||||
|
||||
resource "corsschool_class" "myclass" {
|
||||
name = "meow"
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ tokio-stream = { version = "0.1.15", features = ["net"] }
|
|||
tokio-util = "0.7.10"
|
||||
tonic = { version = "0.11.0", features = ["tls"] }
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
async-trait = "0.1.80"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
use std::future::Future;
|
||||
|
||||
use crate::{
|
||||
provider::{MkDataSource, ProviderData},
|
||||
provider::{BoxFut, MkDataSource, ProviderData},
|
||||
values::Value,
|
||||
Schema,
|
||||
};
|
||||
|
||||
use super::DResult;
|
||||
|
||||
pub trait DataSource: Send + Sync + 'static {
|
||||
pub trait DataSource: Sized + Send + Sync + 'static {
|
||||
type ProviderData: ProviderData;
|
||||
|
||||
// todo: probably want some kind of Value+Schema thing like tfsdk? whatever.
|
||||
fn read(&self, config: Value) -> impl Future<Output = DResult<Value>> + Send + Sync;
|
||||
|
||||
fn name(provider_name: &str) -> String
|
||||
where
|
||||
Self: Sized;
|
||||
fn schema() -> Schema
|
||||
where
|
||||
Self: Sized;
|
||||
fn new(data: Self::ProviderData) -> DResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn name(provider_name: &str) -> String;
|
||||
fn schema() -> Schema;
|
||||
fn new(data: Self::ProviderData) -> DResult<Self>;
|
||||
|
||||
fn erase() -> MkDataSource<Self::ProviderData>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn erase() -> MkDataSource<Self::ProviderData> {
|
||||
MkDataSource::create::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait DynDataSource: Send + Sync + 'static {
|
||||
fn read(&self, config: Value) -> BoxFut<'_, DResult<Value>>;
|
||||
}
|
||||
|
||||
impl<Ds: DataSource> DynDataSource for Ds {
|
||||
fn read(&self, config: Value) -> BoxFut<'_, DResult<Value>> {
|
||||
Box::pin(DataSource::read(self, config))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ pub use values::*;
|
|||
|
||||
pub use terustform_macros::Model;
|
||||
|
||||
pub use async_trait::async_trait;
|
||||
pub use eyre;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
// --------
|
||||
// Rest of the file.
|
||||
|
|
@ -29,6 +31,9 @@ use tracing::Level;
|
|||
pub async fn start<P: Provider>(provider: P) -> eyre::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::DEBUG)
|
||||
.with_env_filter(EnvFilter::builder().parse_lossy(
|
||||
std::env::var("RUST_LOG").unwrap_or_else(|_| "h2=info,rustls=info,debug".into()),
|
||||
))
|
||||
.with_writer(std::io::stderr)
|
||||
.without_time()
|
||||
.init();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
use std::{any::Any, future::Future, marker::PhantomData, pin::Pin, sync::Arc};
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
|
||||
use crate::{datasource::DataSource, resource::Resource, DResult, Schema, Value};
|
||||
use crate::{
|
||||
datasource::{DataSource, DynDataSource},
|
||||
resource::{DynResource, Resource},
|
||||
DResult, Schema, Value,
|
||||
};
|
||||
|
||||
// This setup is a bit complicated.
|
||||
// In this explanation, substitute "`Resource`" for "`Resource` or `DataSource`".
|
||||
|
|
@ -14,29 +18,24 @@ use crate::{datasource::DataSource, resource::Resource, DResult, Schema, Value};
|
|||
pub trait ProviderData: Clone + Send + Sync + 'static {}
|
||||
impl<D: Clone + Send + Sync + 'static> ProviderData for D {}
|
||||
|
||||
pub(super) type BoxFut<'a, O> = Pin<Box<dyn Future<Output = O> + Send + Sync + 'a>>;
|
||||
|
||||
pub struct MkDataSource<D: ProviderData> {
|
||||
pub(crate) name: fn(&str) -> String,
|
||||
pub(crate) schema: Schema,
|
||||
pub(crate) mk: fn(D) -> DResult<StoredDataSource<D>>,
|
||||
pub(crate) mk: fn(D) -> DResult<StoredDataSource>,
|
||||
}
|
||||
|
||||
pub(crate) struct StoredDataSource<D: ProviderData> {
|
||||
pub(crate) object: Arc<dyn Any + Send + Sync>,
|
||||
pub(crate) read: fn(
|
||||
s: &(dyn Any + Send + Sync),
|
||||
config: Value,
|
||||
) -> Pin<Box<dyn Future<Output = DResult<Value>> + Send + Sync + '_>>,
|
||||
pub(crate) struct StoredDataSource {
|
||||
pub(crate) ds: Arc<dyn DynDataSource>,
|
||||
pub(crate) schema: Schema,
|
||||
p: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<D: ProviderData> Clone for StoredDataSource<D> {
|
||||
impl Clone for StoredDataSource {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
object: self.object.clone(),
|
||||
read: self.read,
|
||||
ds: self.ds.clone(),
|
||||
schema: self.schema.clone(),
|
||||
p: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,15 +47,8 @@ impl<D: ProviderData> MkDataSource<D> {
|
|||
schema: Ds::schema(),
|
||||
mk: |data| {
|
||||
Ok(StoredDataSource {
|
||||
object: Arc::new(Ds::new(data)?),
|
||||
read: |s, config| {
|
||||
Box::pin(async {
|
||||
let ds = s.downcast_ref::<Ds>().unwrap();
|
||||
ds.read(config).await
|
||||
})
|
||||
},
|
||||
ds: Arc::new(Ds::new(data)?),
|
||||
schema: Ds::schema(),
|
||||
p: PhantomData,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
@ -66,15 +58,15 @@ impl<D: ProviderData> MkDataSource<D> {
|
|||
pub struct MkResource<D: ProviderData> {
|
||||
pub(crate) name: fn(&str) -> String,
|
||||
pub(crate) schema: Schema,
|
||||
pub(crate) mk: fn(D) -> DResult<StoredResource<D>>,
|
||||
pub(crate) mk: fn(D) -> DResult<StoredResource>,
|
||||
}
|
||||
|
||||
pub(crate) struct StoredResource<D: ProviderData> {
|
||||
pub(crate) ds: Arc<dyn Resource<ProviderData = D>>,
|
||||
pub(crate) struct StoredResource {
|
||||
pub(crate) ds: Arc<dyn DynResource>,
|
||||
pub(crate) schema: Schema,
|
||||
}
|
||||
|
||||
impl<D: ProviderData> Clone for StoredResource<D> {
|
||||
impl Clone for StoredResource {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
ds: self.ds.clone(),
|
||||
|
|
|
|||
|
|
@ -1,35 +1,49 @@
|
|||
use std::future::Future;
|
||||
|
||||
use crate::{
|
||||
provider::{MkResource, ProviderData},
|
||||
provider::{BoxFut, MkResource, ProviderData},
|
||||
values::Value,
|
||||
Schema,
|
||||
};
|
||||
|
||||
use super::DResult;
|
||||
|
||||
#[crate::async_trait]
|
||||
pub trait Resource: Send + Sync + 'static {
|
||||
pub trait Resource: Sized + Send + Sync + 'static {
|
||||
type ProviderData: ProviderData;
|
||||
|
||||
// todo: probably want some kind of Value+Schema thing like tfsdk? whatever.
|
||||
async fn read(&self, config: Value) -> DResult<Value>;
|
||||
async fn create(&self, config: Value) -> DResult<Value>;
|
||||
async fn update(&self, config: Value) -> DResult<Value>;
|
||||
async fn delete(&self, config: Value) -> DResult<Value>;
|
||||
fn read(&self, config: Value) -> impl Future<Output = DResult<Value>> + Send + Sync;
|
||||
fn create(&self, config: Value) -> impl Future<Output = DResult<Value>> + Send + Sync;
|
||||
fn update(&self, config: Value) -> impl Future<Output = DResult<Value>> + Send + Sync;
|
||||
fn delete(&self, state: Value) -> impl Future<Output = DResult<Value>> + Send + Sync;
|
||||
|
||||
fn name(provider_name: &str) -> String
|
||||
where
|
||||
Self: Sized;
|
||||
fn schema() -> Schema
|
||||
where
|
||||
Self: Sized;
|
||||
fn new(data: Self::ProviderData) -> DResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn name(provider_name: &str) -> String;
|
||||
fn schema() -> Schema;
|
||||
fn new(data: Self::ProviderData) -> DResult<Self>;
|
||||
|
||||
fn erase() -> MkResource<Self::ProviderData>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn erase() -> MkResource<Self::ProviderData> {
|
||||
MkResource::create::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait DynResource: Send + Sync + 'static {
|
||||
fn read(&self, config: Value) -> BoxFut<'_, DResult<Value>>;
|
||||
fn create(&self, config: Value) -> BoxFut<'_, DResult<Value>>;
|
||||
fn update(&self, config: Value) -> BoxFut<'_, DResult<Value>>;
|
||||
fn delete(&self, config: Value) -> BoxFut<'_, DResult<Value>>;
|
||||
}
|
||||
|
||||
impl<R: Resource> DynResource for R {
|
||||
fn read(&self, config: Value) -> BoxFut<'_, DResult<Value>> {
|
||||
Box::pin(Resource::read(self, config))
|
||||
}
|
||||
fn create(&self, config: Value) -> BoxFut<'_, DResult<Value>> {
|
||||
Box::pin(Resource::create(self, config))
|
||||
}
|
||||
fn update(&self, config: Value) -> BoxFut<'_, DResult<Value>> {
|
||||
Box::pin(Resource::update(self, config))
|
||||
}
|
||||
fn delete(&self, state: Value) -> BoxFut<'_, DResult<Value>> {
|
||||
Box::pin(Resource::create(self, state))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ enum ProviderState<P: Provider> {
|
|||
diags: Diagnostics,
|
||||
},
|
||||
Configured {
|
||||
data_sources: HashMap<String, StoredDataSource<P::Data>>,
|
||||
resources: HashMap<String, StoredResource<P::Data>>,
|
||||
data_sources: HashMap<String, StoredDataSource>,
|
||||
resources: HashMap<String, StoredResource>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ impl<P: Provider> ProviderHandler<P> {
|
|||
type_name: &str,
|
||||
config: &Option<tfplugin6::DynamicValue>,
|
||||
) -> (Option<tfplugin6::DynamicValue>, Vec<tfplugin6::Diagnostic>) {
|
||||
let ds: StoredDataSource<P::Data> = {
|
||||
let ds: StoredDataSource = {
|
||||
let state = self.state.lock().await;
|
||||
match &*state {
|
||||
ProviderState::Setup { .. } => {
|
||||
|
|
@ -205,7 +205,7 @@ impl<P: Provider> ProviderHandler<P> {
|
|||
}
|
||||
};
|
||||
|
||||
let state = (ds.read)(&*ds.object, config).await;
|
||||
let state = ds.ds.read(config).await;
|
||||
let (state, diagnostics) = match state {
|
||||
Ok(s) => (
|
||||
Some(tfplugin6::DynamicValue {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue