mirror of
https://github.com/Noratrieb/terustform.git
synced 2026-01-14 16:35:11 +01:00
Support nested object
This commit is contained in:
parent
55506d3748
commit
b50fa51e9c
8 changed files with 143 additions and 96 deletions
|
|
@ -1,5 +1,3 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use terustform::{
|
||||
resource::Resource, AttrPath, Attribute, DResult, EyreExt, Mode, Schema, Value, ValueModel,
|
||||
};
|
||||
|
|
@ -78,41 +76,28 @@ impl Resource for ClassResource {
|
|||
fn schema() -> terustform::Schema {
|
||||
Schema {
|
||||
description: "A class".into(),
|
||||
attributes: HashMap::from([
|
||||
(
|
||||
"id".to_owned(),
|
||||
// TODO: UUID validation :3
|
||||
Attribute::String {
|
||||
attributes: terustform::attrs! {
|
||||
"id" => Attribute::String {
|
||||
description: "The UUID".to_owned(),
|
||||
mode: Mode::Computed,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"name".to_owned(),
|
||||
Attribute::String {
|
||||
"name" => Attribute::String {
|
||||
description: "The description".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"description".to_owned(),
|
||||
Attribute::String {
|
||||
"description" => Attribute::String {
|
||||
description: "The description".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"discord_id".to_owned(),
|
||||
Attribute::String {
|
||||
"discord_id" => Attribute::String {
|
||||
description: "The discord ID of the class".to_owned(),
|
||||
mode: Mode::Optional,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use eyre::Context;
|
||||
use terustform::{
|
||||
datasource::DataSource, Attribute, DResult, EyreExt, Mode, Schema, StringValue, Value,
|
||||
|
|
@ -41,14 +39,13 @@ impl DataSource for HugoDataSource {
|
|||
fn schema() -> Schema {
|
||||
Schema {
|
||||
description: "Get Hugo Boss".to_owned(),
|
||||
attributes: HashMap::from([(
|
||||
"hugo".to_owned(),
|
||||
Attribute::String {
|
||||
attributes: terustform::attrs! {
|
||||
"hugo" => Attribute::String {
|
||||
description: "Hugo Boss".to_owned(),
|
||||
mode: Mode::Computed,
|
||||
sensitive: false,
|
||||
},
|
||||
)]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use terustform::{
|
||||
datasource::DataSource, AttrPath, Attribute, DResult, Mode, Schema, StringValue, Value,
|
||||
ValueModel,
|
||||
|
|
@ -13,7 +11,13 @@ pub struct ExampleDataSource {}
|
|||
struct ExampleDataSourceModel {
|
||||
name: StringValue,
|
||||
meow: StringValue,
|
||||
id: StringValue,
|
||||
paws: ExampleDataSourceModelPaws,
|
||||
}
|
||||
|
||||
#[derive(terustform::Model)]
|
||||
struct ExampleDataSourceModelPaws {
|
||||
left: StringValue,
|
||||
right: StringValue,
|
||||
}
|
||||
|
||||
impl DataSource for ExampleDataSource {
|
||||
|
|
@ -26,32 +30,35 @@ impl DataSource for ExampleDataSource {
|
|||
fn schema() -> Schema {
|
||||
Schema {
|
||||
description: "an example".to_owned(),
|
||||
attributes: HashMap::from([
|
||||
(
|
||||
"name".to_owned(),
|
||||
Attribute::String {
|
||||
attributes: terustform::attrs! {
|
||||
"name" => Attribute::String {
|
||||
description: "a cool name".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"meow".to_owned(),
|
||||
Attribute::String {
|
||||
"meow" => Attribute::String {
|
||||
description: "the meow of the cat".to_owned(),
|
||||
mode: Mode::Computed,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"id".to_owned(),
|
||||
Attribute::String {
|
||||
"paws" => Attribute::Object {
|
||||
description: "the ID of the meowy cat".to_owned(),
|
||||
mode: Mode::Computed,
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
attrs: terustform::attrs! {
|
||||
"left" => Attribute::String {
|
||||
description: "meow".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
),
|
||||
]),
|
||||
"right" => Attribute::String {
|
||||
description: "meow".to_owned(),
|
||||
mode: Mode::Required,
|
||||
sensitive: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +74,7 @@ impl DataSource for ExampleDataSource {
|
|||
let meow = format!("mrrrrr i am {name_str}");
|
||||
|
||||
model.meow = StringValue::Known(meow);
|
||||
model.id = StringValue::Known("0".to_owned());
|
||||
model.paws.right = StringValue::Known("O".to_owned());
|
||||
|
||||
Ok(model.to_value())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,18 @@ data "corsschool_class" "test" {
|
|||
output "class" {
|
||||
value = data.corsschool_class.test
|
||||
}
|
||||
|
||||
/*
|
||||
resource "corsschool_class" "myclass" {
|
||||
name = "meow"
|
||||
description = "???"
|
||||
}*/
|
||||
data "corsschool_kitty" "name" {
|
||||
name = "a"
|
||||
paws = {
|
||||
left = "x"
|
||||
right = "y"
|
||||
}
|
||||
}
|
||||
output "kitty_paw" {
|
||||
value = data.corsschool_kitty.name.paws.right
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ fn data_source_model_inner(
|
|||
let #tf::Some(#name) = obj.remove(#name_str) else {
|
||||
return #tf::Err(
|
||||
#tf::Diagnostics::from(#tf::Diagnostic::error_string(
|
||||
format!("Expected property '{}', which was not present", #name_str),
|
||||
format!("Expected property '{}' when deserializing value, which was not present in the value", #name_str),
|
||||
).with_path(path.clone()))
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,9 +29,12 @@ use provider::Provider;
|
|||
|
||||
pub async fn start<P: Provider>(provider: P) -> eyre::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::builder().parse_lossy(
|
||||
std::env::var("RUST_LOG").unwrap_or_else(|_| "h2=info,rustls=info,hyper_util=info,debug".into()),
|
||||
))
|
||||
.with_env_filter(
|
||||
EnvFilter::builder().parse_lossy(
|
||||
std::env::var("RUST_LOG")
|
||||
.unwrap_or_else(|_| "h2=info,rustls=info,hyper_util=info,debug".into()),
|
||||
),
|
||||
)
|
||||
.with_writer(std::io::stderr)
|
||||
.without_time()
|
||||
.init();
|
||||
|
|
@ -39,6 +42,28 @@ pub async fn start<P: Provider>(provider: P) -> eyre::Result<()> {
|
|||
server::serve(provider).await
|
||||
}
|
||||
|
||||
/// ```rust
|
||||
/// # use std::collections::HashMap;
|
||||
/// let x: HashMap<String, u8> = terustform::attrs! {
|
||||
/// "hello" => 0,
|
||||
/// };
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! attrs {
|
||||
(
|
||||
$( $name:literal => $rhs:expr ,)*
|
||||
) => {
|
||||
<$crate::__derive_private::HashMap<_, _> as $crate::__derive_private::FromIterator<(_, _)>>::from_iter([
|
||||
$(
|
||||
(
|
||||
$name.into(),
|
||||
$rhs,
|
||||
),
|
||||
)*
|
||||
])
|
||||
};
|
||||
}
|
||||
|
||||
/// Private, only for use for with the derive macro.
|
||||
#[doc(hidden)]
|
||||
pub mod __derive_private {
|
||||
|
|
@ -46,7 +71,7 @@ pub mod __derive_private {
|
|||
AttrPath, AttrPathSegment, BaseValue, DResult, Diagnostic, Diagnostics, Value, ValueKind,
|
||||
ValueModel,
|
||||
};
|
||||
pub use {Clone, Option::Some, Result::Err, ToOwned};
|
||||
pub use {std::collections::HashMap, Clone, FromIterator, Option::Some, Result::Err, ToOwned};
|
||||
|
||||
pub fn new_object<const N: usize>(elems: [(&str, Value); N]) -> Value {
|
||||
Value::Known(ValueKind::Object(std::collections::BTreeMap::from_iter(
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ pub enum Attribute {
|
|||
mode: Mode,
|
||||
sensitive: bool,
|
||||
},
|
||||
Object {
|
||||
description: String,
|
||||
mode: Mode,
|
||||
sensitive: bool,
|
||||
attrs: HashMap<String, Attribute>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -35,6 +41,7 @@ impl Attribute {
|
|||
match *self {
|
||||
Self::Int64 { mode, .. } => mode,
|
||||
Self::String { mode, .. } => mode,
|
||||
Self::Object { mode, .. } => mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,22 +62,28 @@ impl Mode {
|
|||
|
||||
impl Schema {
|
||||
pub fn typ(&self) -> Type {
|
||||
let attrs = self
|
||||
.attributes
|
||||
.iter()
|
||||
.map(|(name, attr)| {
|
||||
let attr_type = match attr {
|
||||
attrs_typ(&self.attributes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
pub fn typ(&self) -> Type {
|
||||
match self {
|
||||
Attribute::Int64 { .. } => Type::Number,
|
||||
Attribute::String { .. } => Type::String,
|
||||
};
|
||||
Attribute::Object { attrs, .. } => attrs_typ(attrs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(name.clone(), attr_type)
|
||||
})
|
||||
fn attrs_typ(attrs: &HashMap<String, Attribute>) -> Type {
|
||||
let attrs = attrs
|
||||
.iter()
|
||||
.map(|(name, attr)| (name.clone(), attr.typ()))
|
||||
.collect();
|
||||
|
||||
Type::Object {
|
||||
attrs,
|
||||
optionals: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{values::Type, AttrPathSegment, Attribute, Diagnostics, Mode, Schema, Value};
|
||||
use crate::{AttrPathSegment, Attribute, Diagnostics, Mode, Schema, Value};
|
||||
|
||||
use super::grpc::tfplugin6;
|
||||
|
||||
|
|
@ -43,13 +43,14 @@ impl Attribute {
|
|||
attr.computed = mode.computed();
|
||||
};
|
||||
|
||||
attr.r#type = self.typ().to_json().into_bytes();
|
||||
|
||||
match self {
|
||||
Attribute::String {
|
||||
description,
|
||||
mode,
|
||||
sensitive,
|
||||
} => {
|
||||
attr.r#type = Type::String.to_json().into_bytes();
|
||||
attr.description = description;
|
||||
set_modes(&mut attr, mode);
|
||||
attr.sensitive = sensitive;
|
||||
|
|
@ -59,7 +60,16 @@ impl Attribute {
|
|||
mode,
|
||||
sensitive,
|
||||
} => {
|
||||
attr.r#type = Type::Number.to_json().into_bytes();
|
||||
attr.description = description;
|
||||
set_modes(&mut attr, mode);
|
||||
attr.sensitive = sensitive;
|
||||
}
|
||||
Attribute::Object {
|
||||
description,
|
||||
mode,
|
||||
sensitive,
|
||||
attrs: _,
|
||||
} => {
|
||||
attr.description = description;
|
||||
set_modes(&mut attr, mode);
|
||||
attr.sensitive = sensitive;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue