From 6d4fd2178e71db0cc21a24b30004a75d60674d1f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:53:36 +0200 Subject: [PATCH] attempt to fix unknown values --- terustform/src/schema.rs | 10 ++++- terustform/src/server/grpc.rs | 14 ++++++- terustform/src/server/handler.rs | 66 +++++++++++++++++++++++++++++++- terustform/src/server/mod.rs | 1 + 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/terustform/src/schema.rs b/terustform/src/schema.rs index 7645add..8d2dc0a 100644 --- a/terustform/src/schema.rs +++ b/terustform/src/schema.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use crate::Type; - #[derive(Clone)] pub struct Schema { pub description: String, @@ -31,6 +30,15 @@ pub enum Mode { Computed, } +impl Attribute { + pub fn mode(&self) -> Mode { + match *self { + Self::Int64 { mode, .. } => mode, + Self::String { mode, .. } => mode, + } + } +} + impl Mode { pub fn required(&self) -> bool { matches!(self, Self::Required) diff --git a/terustform/src/server/grpc.rs b/terustform/src/server/grpc.rs index e4ce584..429127e 100644 --- a/terustform/src/server/grpc.rs +++ b/terustform/src/server/grpc.rs @@ -189,14 +189,24 @@ impl Provider for super::ProviderHandler

{ request: Request, ) -> Result, Status> { tracing::info!(name=?request.get_ref().type_name, "plan_resource_change"); + let req = request.get_ref(); // We don't do anything interesting like requires_replace for now. + // We're supposed to handle defaults here. + let (planned_state, diagnostics) = self + .do_plan_resource_change( + &req.type_name, + &req.prior_state, + &req.proposed_new_state, + &req.config, + ) + .await; let reply = tfplugin6::plan_resource_change::Response { - planned_state: request.into_inner().proposed_new_state, + planned_state, requires_replace: vec![], planned_private: vec![], - diagnostics: vec![], + diagnostics, legacy_type_system: false, deferred: None, }; diff --git a/terustform/src/server/handler.rs b/terustform/src/server/handler.rs index 1f88d77..aabe1f5 100644 --- a/terustform/src/server/handler.rs +++ b/terustform/src/server/handler.rs @@ -6,7 +6,7 @@ use tracing::{debug, info}; use crate::{ provider::{MkDataSource, MkResource, Provider, StoredDataSource, StoredResource}, - DResult, Diagnostic, Diagnostics, Type, Value, + Attribute, DResult, Diagnostic, Diagnostics, Type, Value, ValueKind, }; use super::{grpc::tfplugin6, Schemas}; @@ -233,6 +233,70 @@ impl ProviderHandler

{ (new_state.into_tfplugin(), TF_OK) } + pub(super) async fn do_plan_resource_change( + &self, + type_name: &str, + prior_state: &Option, + proposed_new_state: &Option, + config: &Option, + ) -> (Option, Vec) { + let rs: StoredResource = { + let state = self.state.lock().await; + match &*state { + ProviderState::Setup { .. } => { + unreachable!("must be set up before calling data sources") + } + ProviderState::Failed { diags } => { + return (None, diags.clone().into_tfplugin_diags()) + } + ProviderState::Configured { + data_sources: _, + resources, + } => resources.get(type_name).unwrap().clone(), + } + }; + let typ = rs.schema.typ(); + let _prior_state = tf_try!(parse_dynamic_value(prior_state, &typ)); + let proposed_new_state = tf_try!(parse_dynamic_value(proposed_new_state, &typ)); + let _config = tf_try!(parse_dynamic_value(config, &typ)); + + // TODO: i cannot even start on how bad this is... + enum AttrSchema<'a> { + Nested(&'a HashMap), + Computed, + End, + } + fn transform(value: Value, schema: AttrSchema) -> Value { + match (value, schema) { + (Value::Null, AttrSchema::Computed) => Value::Unknown, + (Value::Known(ValueKind::Object(attrs)), AttrSchema::Nested(schema)) => { + Value::Known(ValueKind::Object( + attrs + .into_iter() + .map(|(name, attr)| { + let schema = schema.get(&name).unwrap(); + let schema = if schema.mode().computed() { + AttrSchema::Computed + } else { + AttrSchema::End + }; + (name, transform(attr, schema)) + }) + .collect(), + )) + } + (value, _) => value, + } + } + + let planned_state = transform( + proposed_new_state, + AttrSchema::Nested(&rs.schema.attributes), + ); + + (planned_state.into_tfplugin(), TF_OK) + } + pub(super) async fn do_apply_resource_change( &self, type_name: &str, diff --git a/terustform/src/server/mod.rs b/terustform/src/server/mod.rs index 16d87d9..996323a 100644 --- a/terustform/src/server/mod.rs +++ b/terustform/src/server/mod.rs @@ -22,6 +22,7 @@ pub use grpc::Controller; use self::grpc::tfplugin6; use self::handler::ProviderHandler; +#[derive(Debug)] struct Schemas { resources: HashMap, data_sources: HashMap,