attempt to fix unknown values

This commit is contained in:
nora 2024-04-29 21:53:36 +02:00
parent f46d9b299d
commit 6d4fd2178e
4 changed files with 87 additions and 4 deletions

View file

@ -2,7 +2,6 @@ use std::collections::HashMap;
use crate::Type; use crate::Type;
#[derive(Clone)] #[derive(Clone)]
pub struct Schema { pub struct Schema {
pub description: String, pub description: String,
@ -31,6 +30,15 @@ pub enum Mode {
Computed, Computed,
} }
impl Attribute {
pub fn mode(&self) -> Mode {
match *self {
Self::Int64 { mode, .. } => mode,
Self::String { mode, .. } => mode,
}
}
}
impl Mode { impl Mode {
pub fn required(&self) -> bool { pub fn required(&self) -> bool {
matches!(self, Self::Required) matches!(self, Self::Required)

View file

@ -189,14 +189,24 @@ impl<P: crate::provider::Provider> Provider for super::ProviderHandler<P> {
request: Request<tfplugin6::plan_resource_change::Request>, request: Request<tfplugin6::plan_resource_change::Request>,
) -> Result<Response<tfplugin6::plan_resource_change::Response>, Status> { ) -> Result<Response<tfplugin6::plan_resource_change::Response>, Status> {
tracing::info!(name=?request.get_ref().type_name, "plan_resource_change"); 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 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 { let reply = tfplugin6::plan_resource_change::Response {
planned_state: request.into_inner().proposed_new_state, planned_state,
requires_replace: vec![], requires_replace: vec![],
planned_private: vec![], planned_private: vec![],
diagnostics: vec![], diagnostics,
legacy_type_system: false, legacy_type_system: false,
deferred: None, deferred: None,
}; };

View file

@ -6,7 +6,7 @@ use tracing::{debug, info};
use crate::{ use crate::{
provider::{MkDataSource, MkResource, Provider, StoredDataSource, StoredResource}, provider::{MkDataSource, MkResource, Provider, StoredDataSource, StoredResource},
DResult, Diagnostic, Diagnostics, Type, Value, Attribute, DResult, Diagnostic, Diagnostics, Type, Value, ValueKind,
}; };
use super::{grpc::tfplugin6, Schemas}; use super::{grpc::tfplugin6, Schemas};
@ -233,6 +233,70 @@ impl<P: Provider> ProviderHandler<P> {
(new_state.into_tfplugin(), TF_OK) (new_state.into_tfplugin(), TF_OK)
} }
pub(super) async fn do_plan_resource_change(
&self,
type_name: &str,
prior_state: &Option<tfplugin6::DynamicValue>,
proposed_new_state: &Option<tfplugin6::DynamicValue>,
config: &Option<tfplugin6::DynamicValue>,
) -> (Option<tfplugin6::DynamicValue>, Vec<tfplugin6::Diagnostic>) {
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<String, Attribute>),
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( pub(super) async fn do_apply_resource_change(
&self, &self,
type_name: &str, type_name: &str,

View file

@ -22,6 +22,7 @@ pub use grpc::Controller;
use self::grpc::tfplugin6; use self::grpc::tfplugin6;
use self::handler::ProviderHandler; use self::handler::ProviderHandler;
#[derive(Debug)]
struct Schemas { struct Schemas {
resources: HashMap<String, tfplugin6::Schema>, resources: HashMap<String, tfplugin6::Schema>,
data_sources: HashMap<String, tfplugin6::Schema>, data_sources: HashMap<String, tfplugin6::Schema>,