tf_provider/
resource.rs

1// This file is part of the tf-provider project
2//
3// Copyright (C) ANEO, 2024-2024. All rights reserved.
4//
5// Licensed under the Apache License, Version 2.0 (the "License")
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! [`Resource`] module
18
19use crate::attribute_path::AttributePath;
20use crate::diagnostics::Diagnostics;
21use crate::raw::RawValue;
22use crate::schema::Schema;
23use crate::utils::OptionFactor;
24
25use async_trait::async_trait;
26use serde::{Deserialize, Serialize};
27
28/// Trait for implementing a resource with automatic serialization/deserialization
29///
30/// See also: [`DynamicResource`]
31#[async_trait]
32pub trait Resource: Send + Sync {
33    /// State of the resource
34    ///
35    /// The state will be automatically serialized/deserialized at the border of the request.
36    type State<'a>: Serialize + Deserialize<'a> + Send;
37
38    /// Private state of the resource
39    ///
40    /// The private state will be automatically serialized/deserialized at the border of the request.
41    type PrivateState<'a>: Serialize + Deserialize<'a> + Send;
42
43    /// State of the provider metadata
44    ///
45    /// The state will be automatically serialized/deserialized at the border of the request.
46    type ProviderMetaState<'a>: Serialize + Deserialize<'a> + Send;
47
48    /// Get the schema of the resource
49    ///
50    /// # Arguments
51    ///
52    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
53    ///
54    /// # Remarks
55    ///
56    /// The return is ignored if there is an error in diagnostics.
57    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
58    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema>;
59
60    /// Validate the configuration of the resource
61    ///
62    /// # Arguments
63    ///
64    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
65    /// * `config` - State as declared in the Terraform file
66    ///
67    /// # Remarks
68    ///
69    /// The return is ignored if there is an error in diagnostics.
70    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
71    async fn validate<'a>(&self, diags: &mut Diagnostics, config: Self::State<'a>) -> Option<()> {
72        _ = diags;
73        _ = config;
74        Some(())
75    }
76
77    /// Read the new state of the resource
78    ///
79    /// # Arguments
80    ///
81    /// * `diags` - Diagnostics to record warnings and errors that occured during the read
82    /// * `state` - State as stored in the Terraform state
83    /// * `private_state` - Private state as stored in the Terraform state
84    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
85    ///
86    /// # Remarks
87    ///
88    /// Return must be [`None`] if the resource has been destroyed externally.
89    /// Return must be [`Some`] if the resource is still there, even if there was errors while reading the resource.
90    async fn read<'a>(
91        &self,
92        diags: &mut Diagnostics,
93        state: Self::State<'a>,
94        private_state: Self::PrivateState<'a>,
95        provider_meta_state: Self::ProviderMetaState<'a>,
96    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>)>;
97
98    /// Plan the creation of a new resource
99    ///
100    /// # Arguments
101    ///
102    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
103    /// * `proposed_state` - State proposed by Terraform
104    /// * `config_state` - State as declared in the Terraform file
105    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
106    ///
107    /// # Remarks
108    ///
109    /// The return is ignored if there is an error in diagnostics.
110    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
111    async fn plan_create<'a>(
112        &self,
113        diags: &mut Diagnostics,
114        proposed_state: Self::State<'a>,
115        config_state: Self::State<'a>,
116        provider_meta_state: Self::ProviderMetaState<'a>,
117    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>)>;
118
119    /// Plan the changes on the resource
120    ///
121    /// # Arguments
122    ///
123    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
124    /// * `prior_state` - State as stored in the Terraform state
125    /// * `proposed_state` - State proposed by Terraform
126    /// * `config_state` - State as declared in the Terraform file
127    /// * `private_state` - Private state as stored in the Terraform state
128    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
129    ///
130    /// # Remarks
131    ///
132    /// The return is ignored if there is an error in diagnostics.
133    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
134    async fn plan_update<'a>(
135        &self,
136        diags: &mut Diagnostics,
137        prior_state: Self::State<'a>,
138        proposed_state: Self::State<'a>,
139        config_state: Self::State<'a>,
140        prior_private_state: Self::PrivateState<'a>,
141        provider_meta_state: Self::ProviderMetaState<'a>,
142    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>, Vec<AttributePath>)>;
143
144    /// Plan the destruction of the resource
145    ///
146    /// # Arguments
147    ///
148    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
149    /// * `prior_state` - State as stored in the Terraform state
150    /// * `prior_private_state` - Private state as stored in the Terraform state
151    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
152    ///
153    /// # Remarks
154    ///
155    /// The return is ignored if there is an error in diagnostics.
156    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
157    async fn plan_destroy<'a>(
158        &self,
159        diags: &mut Diagnostics,
160        prior_state: Self::State<'a>,
161        prior_private_state: Self::PrivateState<'a>,
162        provider_meta_state: Self::ProviderMetaState<'a>,
163    ) -> Option<Self::PrivateState<'a>>;
164
165    /// Create a new resource
166    ///
167    /// # Arguments
168    ///
169    /// * `diags` - Diagnostics to record warnings and errors that occured during the creation
170    /// * `planned_state` - State proposed by the provider upon plan
171    /// * `config_state` - State as declared in the Terraform file
172    /// * `planned_private_state` - Private state proposed by the provider upon plan
173    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
174    ///
175    /// # Remarks
176    ///
177    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
178    /// Return must be [`Some`] if the resource was created, even if there was errors while creating the resource.
179    async fn create<'a>(
180        &self,
181        diags: &mut Diagnostics,
182        planned_state: Self::State<'a>,
183        config_state: Self::State<'a>,
184        planned_private_state: Self::PrivateState<'a>,
185        provider_meta_state: Self::ProviderMetaState<'a>,
186    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>)>;
187
188    /// Apply the changes on the resource
189    ///
190    /// # Arguments
191    ///
192    /// * `diags` - Diagnostics to record warnings and errors that occured during the update
193    /// * `prior_state` - State as stored in the Terraform state
194    /// * `planned_state` - State proposed by the provider upon plan
195    /// * `config_state` - State as declared in the Terraform file
196    /// * `planned_private_state` - Private state proposed by the provider upon plan
197    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
198    ///
199    /// # Remarks
200    ///
201    /// If the return is [`None`], an ad-hoc error is added to diagnostics, and the resource state is kept unchanged.
202    /// Return must be [`Some`] if the resource was updated, even if there was errors while updated the resource.
203    async fn update<'a>(
204        &self,
205        diags: &mut Diagnostics,
206        prior_state: Self::State<'a>,
207        planned_state: Self::State<'a>,
208        config_state: Self::State<'a>,
209        planned_private_state: Self::PrivateState<'a>,
210        provider_meta_state: Self::ProviderMetaState<'a>,
211    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>)>;
212
213    /// Destroy the resource
214    ///
215    /// # Arguments
216    ///
217    /// * `diags` - Diagnostics to record warnings and errors that occured during the destruction
218    /// * `prior_state` - State as stored in the Terraform state
219    /// * `planned_private_state` - Private state proposed by the provider upon plan
220    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
221    ///
222    /// # Remarks
223    ///
224    /// The return is ignored if there is an error in diagnostics.
225    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
226    async fn destroy<'a>(
227        &self,
228        diags: &mut Diagnostics,
229        prior_state: Self::State<'a>,
230        planned_private_state: Self::PrivateState<'a>,
231        provider_meta_state: Self::ProviderMetaState<'a>,
232    ) -> Option<()>;
233
234    /// Import an existing resource
235    ///
236    /// # Arguments
237    ///
238    /// * `diags` - Diagnostics to record warnings and errors that occured during the import
239    /// * `id` - Opaque string that the provider can use to identify the actual resource to import
240    ///
241    /// # Remarks
242    ///
243    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
244    /// Return must be [`Some`] if the resource was imported, even if there was errors while importing the resource.
245    async fn import<'a>(
246        &self,
247        diags: &mut Diagnostics,
248        id: String,
249    ) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
250        _ = id;
251        diags.root_error_short("Import is not supported");
252        None
253    }
254
255    /// Upgrade the resource from a prior version of the resource
256    ///
257    /// # Arguments
258    ///
259    /// * `diags` - Diagnostics to record warnings and errors that occured during the import
260    /// * `version` - Prior version of the resource to upgrade as recorded in Terraform state
261    /// * `prior_state` - Prior state of the resource to upgrade as recorded in Terraform state
262    ///
263    /// # Remarks
264    ///
265    /// If the return is [`None`], an ad-hoc error is added to diagnostics, and the resource state is kept unchanged.
266    /// Return must be [`Some`] if the resource was upgraded, even if there was errors while upgraded the resource.
267    ///
268    /// Because the schema of the resource might have changed,
269    /// the prior state must be deserialized explicitely.
270    async fn upgrade<'a>(
271        &self,
272        diags: &mut Diagnostics,
273        version: i64,
274        prior_state: RawValue,
275    ) -> Option<Self::State<'a>> {
276        _ = version;
277        _ = prior_state;
278        diags.root_error_short("Upgrade is not supported");
279        None
280    }
281}
282
283/// Trait for implementing a resource *without* automatic serialization/deserialization
284///
285/// See also: [`Resource`]
286#[async_trait]
287pub trait DynamicResource: Send + Sync {
288    /// Get the schema of the resource
289    ///
290    /// # Arguments
291    ///
292    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
293    ///
294    /// # Remarks
295    ///
296    /// The return is ignored if there is an error in diagnostics.
297    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
298    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema>;
299
300    /// Validate the configuration of the resource
301    ///
302    /// # Arguments
303    ///
304    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
305    /// * `config` - State as declared in the Terraform file
306    ///
307    /// # Remarks
308    ///
309    /// The return is ignored if there is an error in diagnostics.
310    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
311    async fn validate(&self, diags: &mut Diagnostics, config: RawValue) -> Option<()> {
312        _ = diags;
313        _ = config;
314        Some(())
315    }
316
317    /// Read the new state of the resource
318    ///
319    /// # Arguments
320    ///
321    /// * `diags` - Diagnostics to record warnings and errors that occured during the read
322    /// * `state` - State as stored in the Terraform state
323    /// * `private_state` - Private state as stored in the Terraform state
324    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
325    ///
326    /// # Remarks
327    ///
328    /// Return must be [`None`] if the resource has been destroyed externally.
329    /// Return must be [`Some`] if the resource is still there, even if there was errors while reading the resource.
330    async fn read(
331        &self,
332        diags: &mut Diagnostics,
333        state: RawValue,
334        private_state: Vec<u8>,
335        provider_meta_state: RawValue,
336    ) -> Option<(RawValue, Vec<u8>)>;
337
338    /// Plan the creation of a new resource
339    ///
340    /// # Arguments
341    ///
342    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
343    /// * `proposed_state` - State proposed by Terraform
344    /// * `config_state` - State as declared in the Terraform file
345    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
346    ///
347    /// # Remarks
348    ///
349    /// The return is ignored if there is an error in diagnostics.
350    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
351    async fn plan_create(
352        &self,
353        diags: &mut Diagnostics,
354        proposed_state: RawValue,
355        config_state: RawValue,
356        provider_meta_state: RawValue,
357    ) -> Option<(RawValue, Vec<u8>)>;
358
359    /// Plan the changes on the resource
360    ///
361    /// # Arguments
362    ///
363    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
364    /// * `prior_state` - State as stored in the Terraform state
365    /// * `proposed_state` - State proposed by Terraform
366    /// * `config_state` - State as declared in the Terraform file
367    /// * `private_state` - Private state as stored in the Terraform state
368    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
369    ///
370    /// # Remarks
371    ///
372    /// The return is ignored if there is an error in diagnostics.
373    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
374    async fn plan_update(
375        &self,
376        diags: &mut Diagnostics,
377        prior_state: RawValue,
378        proposed_state: RawValue,
379        config_state: RawValue,
380        prior_private_state: Vec<u8>,
381        provider_meta_state: RawValue,
382    ) -> Option<(RawValue, Vec<u8>, Vec<AttributePath>)>;
383
384    /// Plan the destruction of the resource
385    ///
386    /// # Arguments
387    ///
388    /// * `diags` - Diagnostics to record warnings and errors that occured during the plan
389    /// * `prior_state` - State as stored in the Terraform state
390    /// * `prior_private_state` - Private state as stored in the Terraform state
391    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
392    ///
393    /// # Remarks
394    ///
395    /// The return is ignored if there is an error in diagnostics.
396    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
397    async fn plan_destroy(
398        &self,
399        diags: &mut Diagnostics,
400        prior_state: RawValue,
401        prior_private_state: Vec<u8>,
402        provider_meta_state: RawValue,
403    ) -> Option<Vec<u8>>;
404
405    /// Create a new resource
406    ///
407    /// # Arguments
408    ///
409    /// * `diags` - Diagnostics to record warnings and errors that occured during the creation
410    /// * `planned_state` - State proposed by the provider upon plan
411    /// * `config_state` - State as declared in the Terraform file
412    /// * `planned_private_state` - Private state proposed by the provider upon plan
413    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
414    ///
415    /// # Remarks
416    ///
417    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
418    /// Return must be [`Some`] if the resource was created, even if there was errors while creating the resource.
419    async fn create(
420        &self,
421        diags: &mut Diagnostics,
422        planned_state: RawValue,
423        config_state: RawValue,
424        planned_private_state: Vec<u8>,
425        provider_meta_state: RawValue,
426    ) -> Option<(RawValue, Vec<u8>)>;
427
428    /// Apply the changes on the resource
429    ///
430    /// # Arguments
431    ///
432    /// * `diags` - Diagnostics to record warnings and errors that occured during the update
433    /// * `prior_state` - State as stored in the Terraform state
434    /// * `planned_state` - State proposed by the provider upon plan
435    /// * `config_state` - State as declared in the Terraform file
436    /// * `planned_private_state` - Private state proposed by the provider upon plan
437    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
438    ///
439    /// # Remarks
440    ///
441    /// If the return is [`None`], an ad-hoc error is added to diagnostics, and the resource state is kept unchanged.
442    /// Return must be [`Some`] if the resource was updated, even if there was errors while updated the resource.
443    async fn update(
444        &self,
445        diags: &mut Diagnostics,
446        prior_state: RawValue,
447        planned_state: RawValue,
448        config_state: RawValue,
449        planned_private_state: Vec<u8>,
450        provider_meta_state: RawValue,
451    ) -> Option<(RawValue, Vec<u8>)>;
452
453    /// Destroy the resource
454    ///
455    /// # Arguments
456    ///
457    /// * `diags` - Diagnostics to record warnings and errors that occured during the destruction
458    /// * `prior_state` - State as stored in the Terraform state
459    /// * `planned_private_state` - Private state proposed by the provider upon plan
460    /// * `provider_meta_state` - State of the provider metadata as declared in the Terraform file
461    ///
462    /// # Remarks
463    ///
464    /// The return is ignored if there is an error in diagnostics.
465    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
466    async fn destroy(
467        &self,
468        diags: &mut Diagnostics,
469        prior_state: RawValue,
470        planned_private_state: Vec<u8>,
471        provider_meta_state: RawValue,
472    ) -> Option<()>;
473
474    /// Import an existing resource
475    ///
476    /// # Arguments
477    ///
478    /// * `diags` - Diagnostics to record warnings and errors that occured during the import
479    /// * `id` - Opaque string that the provider can use to identify the actual resource to import
480    ///
481    /// # Remarks
482    ///
483    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
484    /// Return must be [`Some`] if the resource was imported, even if there was errors while importing the resource.
485    async fn import(&self, diags: &mut Diagnostics, id: String) -> Option<(RawValue, Vec<u8>)> {
486        _ = id;
487        diags.root_error_short("Import is not supported");
488        None
489    }
490
491    /// Upgrade the resource
492    ///
493    /// # Arguments
494    ///
495    /// * `diags` - Diagnostics to record warnings and errors that occured during the import
496    /// * `version` - Prior version of the resource to upgrade as recorded in Terraform state
497    /// * `prior_state` - Prior state of the resource to upgrade as recorded in Terraform state
498    ///
499    /// # Remarks
500    ///
501    /// If the return is [`None`], an ad-hoc error is added to diagnostics, and the resource state is kept unchanged.
502    /// Return must be [`Some`] if the resource was upgraded, even if there was errors while upgraded the resource.
503    async fn upgrade(
504        &self,
505        diags: &mut Diagnostics,
506        version: i64,
507        prior_state: RawValue,
508    ) -> Option<RawValue> {
509        _ = version;
510        _ = prior_state;
511        diags.root_error_short("Upgrade is not supported");
512        None
513    }
514}
515
516#[async_trait]
517impl<T: Resource> DynamicResource for T {
518    /// Get the schema of the resource
519    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
520        <T as Resource>::schema(self, diags)
521    }
522    /// Validate the configuration of the resource
523    async fn validate(&self, diags: &mut Diagnostics, config: RawValue) -> Option<()> {
524        let config = config.deserialize(diags)?;
525        <T as Resource>::validate(self, diags, config).await
526    }
527    /// Read the new state of the resource
528    async fn read(
529        &self,
530        diags: &mut Diagnostics,
531        state: RawValue,
532        private_state: Vec<u8>,
533        provider_meta_state: RawValue,
534    ) -> Option<(RawValue, Vec<u8>)> {
535        let private_state = RawValue::MessagePack(private_state);
536        let (state, private_state, provider_meta_state) = (
537            state.deserialize(diags),
538            private_state.deserialize(diags),
539            provider_meta_state.deserialize(diags),
540        )
541            .factor()?;
542
543        let (state, private_state) =
544            <T as Resource>::read(self, diags, state, private_state, provider_meta_state).await?;
545
546        (
547            RawValue::serialize(diags, &state),
548            RawValue::serialize_vec(diags, &private_state),
549        )
550            .factor()
551    }
552    /// Plan the creation of a new resource
553    async fn plan_create(
554        &self,
555        diags: &mut Diagnostics,
556        proposed_state: RawValue,
557        config_state: RawValue,
558        provider_meta_state: RawValue,
559    ) -> Option<(RawValue, Vec<u8>)> {
560        let (proposed_state, config_state, provider_meta_state) = (
561            proposed_state.deserialize(diags),
562            config_state.deserialize(diags),
563            provider_meta_state.deserialize(diags),
564        )
565            .factor()?;
566
567        let (state, private_state) = <T as Resource>::plan_create(
568            self,
569            diags,
570            proposed_state,
571            config_state,
572            provider_meta_state,
573        )
574        .await?;
575
576        (
577            RawValue::serialize(diags, &state),
578            RawValue::serialize_vec(diags, &private_state),
579        )
580            .factor()
581    }
582    /// Plan the changes on the resource
583    async fn plan_update(
584        &self,
585        diags: &mut Diagnostics,
586        prior_state: RawValue,
587        proposed_state: RawValue,
588        config_state: RawValue,
589        prior_private_state: Vec<u8>,
590        provider_meta_state: RawValue,
591    ) -> Option<(RawValue, Vec<u8>, Vec<AttributePath>)> {
592        let prior_private_state = RawValue::MessagePack(prior_private_state);
593        let (prior_state, proposed_state, config_state, prior_private_state, provider_meta_state) =
594            (
595                prior_state.deserialize(diags),
596                proposed_state.deserialize(diags),
597                config_state.deserialize(diags),
598                prior_private_state.deserialize(diags),
599                provider_meta_state.deserialize(diags),
600            )
601                .factor()?;
602
603        let (state, private_state, destroy_triggers) = <T as Resource>::plan_update(
604            self,
605            diags,
606            prior_state,
607            proposed_state,
608            config_state,
609            prior_private_state,
610            provider_meta_state,
611        )
612        .await?;
613
614        (
615            RawValue::serialize(diags, &state),
616            RawValue::serialize_vec(diags, &private_state),
617            Some(destroy_triggers),
618        )
619            .factor()
620    }
621    /// Plan the destruction of the resource
622    async fn plan_destroy(
623        &self,
624        diags: &mut Diagnostics,
625        prior_state: RawValue,
626        prior_private_state: Vec<u8>,
627        provider_meta_state: RawValue,
628    ) -> Option<Vec<u8>> {
629        let prior_private_state = RawValue::MessagePack(prior_private_state);
630        let (prior_state, prior_private_state, provider_meta_state) = (
631            prior_state.deserialize(diags),
632            prior_private_state.deserialize(diags),
633            provider_meta_state.deserialize(diags),
634        )
635            .factor()?;
636
637        let private_state = <T as Resource>::plan_destroy(
638            self,
639            diags,
640            prior_state,
641            prior_private_state,
642            provider_meta_state,
643        )
644        .await?;
645
646        RawValue::serialize_vec(diags, &private_state)
647    }
648    /// Create a new resource
649    async fn create(
650        &self,
651        diags: &mut Diagnostics,
652        planned_state: RawValue,
653        config_state: RawValue,
654        planned_private_state: Vec<u8>,
655        provider_meta_state: RawValue,
656    ) -> Option<(RawValue, Vec<u8>)> {
657        let planned_private_state = RawValue::MessagePack(planned_private_state);
658        let (planned_state, config_state, planned_private_state, provider_meta_state) = (
659            planned_state.deserialize(diags),
660            config_state.deserialize(diags),
661            planned_private_state.deserialize(diags),
662            provider_meta_state.deserialize(diags),
663        )
664            .factor()?;
665        let (state, private_state) = <T as Resource>::create(
666            self,
667            diags,
668            planned_state,
669            config_state,
670            planned_private_state,
671            provider_meta_state,
672        )
673        .await?;
674        (
675            RawValue::serialize(diags, &state),
676            RawValue::serialize_vec(diags, &private_state),
677        )
678            .factor()
679    }
680    /// Apply the changes on the resource
681    async fn update(
682        &self,
683        diags: &mut Diagnostics,
684        prior_state: RawValue,
685        planned_state: RawValue,
686        config_state: RawValue,
687        planned_private_state: Vec<u8>,
688        provider_meta_state: RawValue,
689    ) -> Option<(RawValue, Vec<u8>)> {
690        let planned_private_state = RawValue::MessagePack(planned_private_state);
691        let (prior_state, planned_state, config_state, planned_private_state, provider_meta_state) =
692            (
693                prior_state.deserialize(diags),
694                planned_state.deserialize(diags),
695                config_state.deserialize(diags),
696                planned_private_state.deserialize(diags),
697                provider_meta_state.deserialize(diags),
698            )
699                .factor()?;
700        let (state, private_state) = <T as Resource>::update(
701            self,
702            diags,
703            prior_state,
704            planned_state,
705            config_state,
706            planned_private_state,
707            provider_meta_state,
708        )
709        .await?;
710        (
711            RawValue::serialize(diags, &state),
712            RawValue::serialize_vec(diags, &private_state),
713        )
714            .factor()
715    }
716    /// Destroy the resource
717    async fn destroy(
718        &self,
719        diags: &mut Diagnostics,
720        prior_state: RawValue,
721        planned_private_state: Vec<u8>,
722        provider_meta_state: RawValue,
723    ) -> Option<()> {
724        let planned_private_state = RawValue::MessagePack(planned_private_state);
725        let (prior_state, planned_private_state, provider_meta_state) = (
726            prior_state.deserialize(diags),
727            planned_private_state.deserialize(diags),
728            provider_meta_state.deserialize(diags),
729        )
730            .factor()?;
731
732        <T as Resource>::destroy(
733            self,
734            diags,
735            prior_state,
736            planned_private_state,
737            provider_meta_state,
738        )
739        .await
740    }
741    /// Import an existing resource
742    async fn import(&self, diags: &mut Diagnostics, id: String) -> Option<(RawValue, Vec<u8>)> {
743        let (state, private_state) = <T as Resource>::import(self, diags, id).await?;
744        (
745            RawValue::serialize(diags, &state),
746            RawValue::serialize_vec(diags, &private_state),
747        )
748            .factor()
749    }
750    /// Upgrade the resource
751    async fn upgrade(
752        &self,
753        diags: &mut Diagnostics,
754        version: i64,
755        prior_state: RawValue,
756    ) -> Option<RawValue> {
757        let state = <T as Resource>::upgrade(self, diags, version, prior_state).await?;
758        RawValue::serialize(diags, &state)
759    }
760}
761
762impl<T: Resource + 'static> From<T> for Box<dyn DynamicResource> {
763    fn from(value: T) -> Self {
764        Box::new(value)
765    }
766}