mirror of
https://github.com/Noratrieb/terustform.git
synced 2026-01-14 16:35:11 +01:00
stuff
This commit is contained in:
parent
854f7bb2bc
commit
85d10ed893
15 changed files with 328 additions and 160 deletions
5
README.md
Normal file
5
README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# terustform
|
||||||
|
|
||||||
|
Terraform/OpenTofu Providers written in Rust!
|
||||||
|
|
||||||
|
**This project is extremely experimental and does not work well.**
|
||||||
1
terraform-provider-corsschool/.gitignore
vendored
Normal file
1
terraform-provider-corsschool/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/.env
|
||||||
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.12"
|
eyre = "0.6.12"
|
||||||
reqwest = { version = "0.12.3", default-features = false, features = ["charset", "http2", "rustls-tls"]}
|
reqwest = { version = "0.12.3", default-features = false, features = ["charset", "http2", "json", "rustls-tls"] }
|
||||||
terustform = { path = "../terustform" }
|
terustform = { path = "../terustform" }
|
||||||
|
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,51 @@
|
||||||
pub struct _CorsClient {
|
use eyre::{Context, OptionExt, Result};
|
||||||
client: reqwest::Client
|
use reqwest::header::{HeaderMap, HeaderValue};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CorsClient {
|
||||||
|
client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
const URL: &str = "https://api.cors-school.nilstrieb.dev/api";
|
||||||
|
|
||||||
|
impl CorsClient {
|
||||||
|
pub async fn new(email: String, password: String) -> Result<Self> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let login = dto::UserLogin { email, password };
|
||||||
|
let token = client
|
||||||
|
.post(format!("{URL}/login"))
|
||||||
|
.json(&login)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.wrap_err("failed to send login request")?;
|
||||||
|
let token = token.error_for_status().wrap_err("failed to login")?;
|
||||||
|
let token = token
|
||||||
|
.headers()
|
||||||
|
.get("Token")
|
||||||
|
.ok_or_eyre("does not have Token header in login response")?
|
||||||
|
.to_str()
|
||||||
|
.wrap_err("Token is invalid utf8")?;
|
||||||
|
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
"Authorization",
|
||||||
|
HeaderValue::from_str(&format!("Bearer {}", token,)).unwrap(),
|
||||||
|
);
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.default_headers(headers)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(Self { client })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_hugo(&self) -> Result<String> {
|
||||||
|
Ok(self
|
||||||
|
.client
|
||||||
|
.get(format!("{URL}/hugo"))
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.text()
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
mod client;
|
mod client;
|
||||||
|
mod resources;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use eyre::Context;
|
||||||
use terustform::{
|
use terustform::{
|
||||||
datasource::{self, DataSource},
|
datasource::DataSource,
|
||||||
provider::{MkDataSource, Provider},
|
provider::{MkDataSource, Provider},
|
||||||
AttrPath, DResult, StringValue, Value, ValueModel,
|
DResult, EyreExt, Schema, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
@ -16,90 +18,36 @@ async fn main() -> eyre::Result<()> {
|
||||||
pub struct ExampleProvider {}
|
pub struct ExampleProvider {}
|
||||||
|
|
||||||
impl Provider for ExampleProvider {
|
impl Provider for ExampleProvider {
|
||||||
type Data = ();
|
type Data = client::CorsClient;
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
"corsschool".to_owned()
|
"corsschool".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schema(&self) -> datasource::Schema {
|
fn schema(&self) -> Schema {
|
||||||
datasource::Schema {
|
Schema {
|
||||||
description: "uwu".to_owned(),
|
description: "uwu".to_owned(),
|
||||||
attributes: HashMap::new(),
|
attributes: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn configure(&self, _config: Value) -> DResult<Self::Data> {
|
async fn configure(&self, _config: Value) -> DResult<Self::Data> {
|
||||||
Ok(())
|
let username = std::env::var("CORSSCHOOL_USERNAME")
|
||||||
|
.wrap_err("CORSSCHOOL_USERNAME environment variable not set")
|
||||||
|
.eyre_to_tf()?;
|
||||||
|
let password = std::env::var("CORSSCHOOL_PASSWORD")
|
||||||
|
.wrap_err("CORSSCHOOL_PASSWORD environment variable not set")
|
||||||
|
.eyre_to_tf()?;
|
||||||
|
let client = client::CorsClient::new(username, password)
|
||||||
|
.await
|
||||||
|
.wrap_err("failed to create client")
|
||||||
|
.eyre_to_tf()?;
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_sources(&self) -> Vec<MkDataSource<Self::Data>> {
|
fn data_sources(&self) -> Vec<MkDataSource<Self::Data>> {
|
||||||
vec![ExampleDataSource::erase()]
|
vec![
|
||||||
}
|
resources::kitty::ExampleDataSource::erase(),
|
||||||
}
|
resources::hugo::HugoDataSource::erase(),
|
||||||
|
]
|
||||||
struct ExampleDataSource {}
|
|
||||||
|
|
||||||
#[derive(terustform::Model)]
|
|
||||||
struct ExampleDataSourceModel {
|
|
||||||
name: StringValue,
|
|
||||||
meow: StringValue,
|
|
||||||
id: StringValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[terustform::async_trait]
|
|
||||||
impl DataSource for ExampleDataSource {
|
|
||||||
type ProviderData = ();
|
|
||||||
|
|
||||||
fn name(provider_name: &str) -> String {
|
|
||||||
format!("{provider_name}_kitty")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn schema() -> datasource::Schema {
|
|
||||||
datasource::Schema {
|
|
||||||
description: "an example".to_owned(),
|
|
||||||
attributes: HashMap::from([
|
|
||||||
(
|
|
||||||
"name".to_owned(),
|
|
||||||
datasource::Attribute::String {
|
|
||||||
description: "a cool name".to_owned(),
|
|
||||||
mode: datasource::Mode::Required,
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"meow".to_owned(),
|
|
||||||
datasource::Attribute::String {
|
|
||||||
description: "the meow of the cat".to_owned(),
|
|
||||||
mode: datasource::Mode::Computed,
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"id".to_owned(),
|
|
||||||
datasource::Attribute::String {
|
|
||||||
description: "the ID of the meowy cat".to_owned(),
|
|
||||||
mode: datasource::Mode::Computed,
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new(_data: Self::ProviderData) -> DResult<Self> {
|
|
||||||
Ok(ExampleDataSource {})
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read(&self, config: Value) -> DResult<Value> {
|
|
||||||
let mut model = ExampleDataSourceModel::from_value(config, &AttrPath::root())?;
|
|
||||||
|
|
||||||
let name_str = model.name.expect_known(AttrPath::attr("name"))?;
|
|
||||||
|
|
||||||
let meow = format!("mrrrrr i am {name_str}");
|
|
||||||
|
|
||||||
model.meow = StringValue::Known(meow);
|
|
||||||
model.id = StringValue::Known("0".to_owned());
|
|
||||||
|
|
||||||
Ok(model.to_value())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
68
terraform-provider-corsschool/src/resources/hugo.rs
Normal file
68
terraform-provider-corsschool/src/resources/hugo.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use eyre::Context;
|
||||||
|
use terustform::{
|
||||||
|
datasource::DataSource, Attribute, DResult, EyreExt, Mode, Schema, StringValue, Value,
|
||||||
|
ValueModel,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::client::CorsClient;
|
||||||
|
|
||||||
|
pub struct HugoDataSource {
|
||||||
|
client: CorsClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(terustform::Model)]
|
||||||
|
struct HugoDataSourceModel {
|
||||||
|
hugo: StringValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[terustform::async_trait]
|
||||||
|
impl DataSource for HugoDataSource {
|
||||||
|
type ProviderData = CorsClient;
|
||||||
|
|
||||||
|
async fn read(&self, _config: Value) -> DResult<Value> {
|
||||||
|
let hugo = self
|
||||||
|
.client
|
||||||
|
.get_hugo()
|
||||||
|
.await
|
||||||
|
.wrap_err("failed to get hugo")
|
||||||
|
.eyre_to_tf()?;
|
||||||
|
|
||||||
|
Ok(HugoDataSourceModel {
|
||||||
|
hugo: StringValue::Known(hugo),
|
||||||
|
}
|
||||||
|
.to_value())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(provider_name: &str) -> String
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
format!("{provider_name}_hugo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema() -> Schema
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Schema {
|
||||||
|
description: "Get Hugo Boss".to_owned(),
|
||||||
|
attributes: HashMap::from([(
|
||||||
|
"hugo".to_owned(),
|
||||||
|
Attribute::String {
|
||||||
|
description: "Hugo Boss".to_owned(),
|
||||||
|
mode: Mode::Computed,
|
||||||
|
sensitive: false,
|
||||||
|
},
|
||||||
|
)]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(data: Self::ProviderData) -> DResult<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Ok(Self { client: data })
|
||||||
|
}
|
||||||
|
}
|
||||||
75
terraform-provider-corsschool/src/resources/kitty.rs
Normal file
75
terraform-provider-corsschool/src/resources/kitty.rs
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use terustform::{
|
||||||
|
datasource::DataSource, AttrPath, Attribute, DResult, Mode, Schema, StringValue, Value,
|
||||||
|
ValueModel,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::client::CorsClient;
|
||||||
|
|
||||||
|
pub struct ExampleDataSource {}
|
||||||
|
|
||||||
|
#[derive(terustform::Model)]
|
||||||
|
struct ExampleDataSourceModel {
|
||||||
|
name: StringValue,
|
||||||
|
meow: StringValue,
|
||||||
|
id: StringValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[terustform::async_trait]
|
||||||
|
impl DataSource for ExampleDataSource {
|
||||||
|
type ProviderData = CorsClient;
|
||||||
|
|
||||||
|
fn name(provider_name: &str) -> String {
|
||||||
|
format!("{provider_name}_kitty")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema() -> Schema {
|
||||||
|
Schema {
|
||||||
|
description: "an example".to_owned(),
|
||||||
|
attributes: HashMap::from([
|
||||||
|
(
|
||||||
|
"name".to_owned(),
|
||||||
|
Attribute::String {
|
||||||
|
description: "a cool name".to_owned(),
|
||||||
|
mode: Mode::Required,
|
||||||
|
sensitive: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"meow".to_owned(),
|
||||||
|
Attribute::String {
|
||||||
|
description: "the meow of the cat".to_owned(),
|
||||||
|
mode: Mode::Computed,
|
||||||
|
sensitive: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"id".to_owned(),
|
||||||
|
Attribute::String {
|
||||||
|
description: "the ID of the meowy cat".to_owned(),
|
||||||
|
mode: Mode::Computed,
|
||||||
|
sensitive: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(_data: Self::ProviderData) -> DResult<Self> {
|
||||||
|
Ok(ExampleDataSource {})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read(&self, config: Value) -> DResult<Value> {
|
||||||
|
let mut model = ExampleDataSourceModel::from_value(config, &AttrPath::root())?;
|
||||||
|
|
||||||
|
let name_str = model.name.expect_known(AttrPath::attr("name"))?;
|
||||||
|
|
||||||
|
let meow = format!("mrrrrr i am {name_str}");
|
||||||
|
|
||||||
|
model.meow = StringValue::Known(meow);
|
||||||
|
model.id = StringValue::Known("0".to_owned());
|
||||||
|
|
||||||
|
Ok(model.to_value())
|
||||||
|
}
|
||||||
|
}
|
||||||
2
terraform-provider-corsschool/src/resources/mod.rs
Normal file
2
terraform-provider-corsschool/src/resources/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod hugo;
|
||||||
|
pub mod kitty;
|
||||||
|
|
@ -22,3 +22,8 @@ output "cat1" {
|
||||||
output "cat2" {
|
output "cat2" {
|
||||||
value = data.corsschool_kitty.hellyes.meow
|
value = data.corsschool_kitty.hellyes.meow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data "corsschool_hugo" "hugo" {}
|
||||||
|
output "hugo" {
|
||||||
|
value = data.corsschool_hugo.hugo
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
provider::{MkDataSource, ProviderData},
|
provider::{MkDataSource, ProviderData},
|
||||||
values::{Type, Value},
|
values::Value,
|
||||||
|
Schema,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::DResult;
|
use super::DResult;
|
||||||
|
|
@ -31,67 +30,3 @@ pub trait DataSource: Send + Sync + 'static {
|
||||||
MkDataSource::create::<Self>()
|
MkDataSource::create::<Self>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Schema {
|
|
||||||
pub description: String,
|
|
||||||
pub attributes: HashMap<String, Attribute>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum Attribute {
|
|
||||||
String {
|
|
||||||
description: String,
|
|
||||||
mode: Mode,
|
|
||||||
sensitive: bool,
|
|
||||||
},
|
|
||||||
Int64 {
|
|
||||||
description: String,
|
|
||||||
mode: Mode,
|
|
||||||
sensitive: bool,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub enum Mode {
|
|
||||||
Required,
|
|
||||||
Optional,
|
|
||||||
OptionalComputed,
|
|
||||||
Computed,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mode {
|
|
||||||
pub fn required(&self) -> bool {
|
|
||||||
matches!(self, Self::Required)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn optional(&self) -> bool {
|
|
||||||
matches!(self, Self::Optional | Self::OptionalComputed)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn computed(&self) -> bool {
|
|
||||||
matches!(self, Self::OptionalComputed | Self::Computed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Schema {
|
|
||||||
pub fn typ(&self) -> Type {
|
|
||||||
let attrs = self
|
|
||||||
.attributes
|
|
||||||
.iter()
|
|
||||||
.map(|(name, attr)| {
|
|
||||||
let attr_type = match attr {
|
|
||||||
Attribute::Int64 { .. } => Type::Number,
|
|
||||||
Attribute::String { .. } => Type::String,
|
|
||||||
};
|
|
||||||
|
|
||||||
(name.clone(), attr_type)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Type::Object {
|
|
||||||
attrs,
|
|
||||||
optionals: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,16 @@ impl AttrPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait EyreExt<T> {
|
||||||
|
fn eyre_to_tf(self) -> DResult<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> EyreExt<T> for Result<T, eyre::Report> {
|
||||||
|
fn eyre_to_tf(self) -> DResult<T> {
|
||||||
|
self.map_err(|e| Diagnostic::error_string(format!("{:?}", e)).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: std::error::Error + std::fmt::Debug> From<E> for Diagnostic {
|
impl<E: std::error::Error + std::fmt::Debug> From<E> for Diagnostic {
|
||||||
fn from(value: E) -> Self {
|
fn from(value: E) -> Self {
|
||||||
Self::error_string(format!("{:?}", value))
|
Self::error_string(format!("{:?}", value))
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
mod diag;
|
// Internal modules
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
|
// Modules re-exported in the root
|
||||||
|
mod diag;
|
||||||
|
mod schema;
|
||||||
mod values;
|
mod values;
|
||||||
|
|
||||||
|
// Public modules
|
||||||
pub mod datasource;
|
pub mod datasource;
|
||||||
pub mod provider;
|
pub mod provider;
|
||||||
|
|
||||||
|
// Re-exports
|
||||||
pub use diag::*;
|
pub use diag::*;
|
||||||
|
pub use schema::*;
|
||||||
pub use values::*;
|
pub use values::*;
|
||||||
|
|
||||||
pub use terustform_macros::Model;
|
pub use terustform_macros::Model;
|
||||||
|
|
@ -13,6 +20,9 @@ pub use terustform_macros::Model;
|
||||||
pub use async_trait::async_trait;
|
pub use async_trait::async_trait;
|
||||||
pub use eyre;
|
pub use eyre;
|
||||||
|
|
||||||
|
// --------
|
||||||
|
// Rest of the file.
|
||||||
|
|
||||||
use provider::Provider;
|
use provider::Provider;
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,19 @@
|
||||||
use std::{future::Future, sync::Arc};
|
use std::{future::Future, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{datasource::DataSource, DResult, Schema, Value};
|
||||||
datasource::{self, DataSource, Schema},
|
|
||||||
DResult, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait ProviderData: Clone + Send + Sync + 'static {}
|
pub trait ProviderData: Clone + Send + Sync + 'static {}
|
||||||
impl<D: Clone + Send + Sync + 'static> ProviderData for D {}
|
impl<D: Clone + Send + Sync + 'static> ProviderData for D {}
|
||||||
|
|
||||||
pub struct MkDataSource<D: ProviderData> {
|
pub struct MkDataSource<D: ProviderData> {
|
||||||
pub(crate) name: fn(&str) -> String,
|
pub(crate) name: fn(&str) -> String,
|
||||||
pub(crate) schema: datasource::Schema,
|
pub(crate) schema: Schema,
|
||||||
pub(crate) mk: fn(D) -> DResult<StoredDataSource<D>>,
|
pub(crate) mk: fn(D) -> DResult<StoredDataSource<D>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct StoredDataSource<D: ProviderData> {
|
pub(crate) struct StoredDataSource<D: ProviderData> {
|
||||||
pub(crate) ds: Arc<dyn DataSource<ProviderData = D>>,
|
pub(crate) ds: Arc<dyn DataSource<ProviderData = D>>,
|
||||||
pub(crate) schema: datasource::Schema,
|
pub(crate) schema: Schema,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: ProviderData> Clone for StoredDataSource<D> {
|
impl<D: ProviderData> Clone for StoredDataSource<D> {
|
||||||
|
|
|
||||||
68
terustform/src/schema.rs
Normal file
68
terustform/src/schema.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::Type;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Schema {
|
||||||
|
pub description: String,
|
||||||
|
pub attributes: HashMap<String, Attribute>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Attribute {
|
||||||
|
String {
|
||||||
|
description: String,
|
||||||
|
mode: Mode,
|
||||||
|
sensitive: bool,
|
||||||
|
},
|
||||||
|
Int64 {
|
||||||
|
description: String,
|
||||||
|
mode: Mode,
|
||||||
|
sensitive: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum Mode {
|
||||||
|
Required,
|
||||||
|
Optional,
|
||||||
|
OptionalComputed,
|
||||||
|
Computed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mode {
|
||||||
|
pub fn required(&self) -> bool {
|
||||||
|
matches!(self, Self::Required)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn optional(&self) -> bool {
|
||||||
|
matches!(self, Self::Optional | Self::OptionalComputed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn computed(&self) -> bool {
|
||||||
|
matches!(self, Self::OptionalComputed | Self::Computed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Schema {
|
||||||
|
pub fn typ(&self) -> Type {
|
||||||
|
let attrs = self
|
||||||
|
.attributes
|
||||||
|
.iter()
|
||||||
|
.map(|(name, attr)| {
|
||||||
|
let attr_type = match attr {
|
||||||
|
Attribute::Int64 { .. } => Type::Number,
|
||||||
|
Attribute::String { .. } => Type::String,
|
||||||
|
};
|
||||||
|
|
||||||
|
(name.clone(), attr_type)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Type::Object {
|
||||||
|
attrs,
|
||||||
|
optionals: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
use crate::{
|
use crate::{values::Type, AttrPathSegment, Attribute, Diagnostics, Mode, Schema};
|
||||||
datasource::{self, Mode},
|
|
||||||
values::Type,
|
|
||||||
AttrPathSegment, Diagnostics,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::grpc::tfplugin6;
|
use super::grpc::tfplugin6;
|
||||||
|
|
||||||
impl datasource::Schema {
|
impl Schema {
|
||||||
pub(crate) fn to_tfplugin(self) -> tfplugin6::Schema {
|
pub(crate) fn to_tfplugin(self) -> tfplugin6::Schema {
|
||||||
tfplugin6::Schema {
|
tfplugin6::Schema {
|
||||||
version: 1,
|
version: 1,
|
||||||
|
|
@ -26,7 +22,7 @@ impl datasource::Schema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl datasource::Attribute {
|
impl Attribute {
|
||||||
pub(crate) fn to_tfplugin(self, name: String) -> tfplugin6::schema::Attribute {
|
pub(crate) fn to_tfplugin(self, name: String) -> tfplugin6::schema::Attribute {
|
||||||
let mut attr = tfplugin6::schema::Attribute {
|
let mut attr = tfplugin6::schema::Attribute {
|
||||||
name,
|
name,
|
||||||
|
|
@ -48,7 +44,7 @@ impl datasource::Attribute {
|
||||||
};
|
};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
datasource::Attribute::String {
|
Attribute::String {
|
||||||
description,
|
description,
|
||||||
mode,
|
mode,
|
||||||
sensitive,
|
sensitive,
|
||||||
|
|
@ -58,7 +54,7 @@ impl datasource::Attribute {
|
||||||
set_modes(&mut attr, mode);
|
set_modes(&mut attr, mode);
|
||||||
attr.sensitive = sensitive;
|
attr.sensitive = sensitive;
|
||||||
}
|
}
|
||||||
datasource::Attribute::Int64 {
|
Attribute::Int64 {
|
||||||
description,
|
description,
|
||||||
mode,
|
mode,
|
||||||
sensitive,
|
sensitive,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue