tf_provider/
provider.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//! [`Provider`] module
18
19use std::collections::HashMap;
20
21use crate::data_source::DynamicDataSource;
22use crate::diagnostics::Diagnostics;
23use crate::function::DynamicFunction;
24use crate::raw::RawValue;
25use crate::resource::DynamicResource;
26use crate::schema::Schema;
27
28use async_trait::async_trait;
29use serde::{Deserialize, Serialize};
30
31/// Trait for implementing a provider with automatic serialization/deserialization
32///
33/// See also: [`DynamicProvider`]
34#[async_trait]
35pub trait Provider: Send + Sync + 'static {
36    /// Configuration of the provider
37    ///
38    /// The state will be automatically serialized/deserialized at the border of the request.
39    type Config<'a>: Serialize + Deserialize<'a> + Send;
40
41    /// State of the provider metadata
42    ///
43    /// The metadata state will be automatically serialized/deserialized at the border of the request.
44    type MetaState<'a>: Serialize + Deserialize<'a> + Send;
45
46    /// Get the schema of the provider
47    ///
48    /// # Arguments
49    ///
50    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
51    ///
52    /// # Remarks
53    ///
54    /// The return is ignored if there is an error in diagnostics.
55    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
56    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema>;
57
58    /// Validate the configuration of the provider
59    ///
60    /// # Arguments
61    ///
62    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
63    /// * `config` - State as declared in the Terraform file
64    ///
65    /// # Remarks
66    ///
67    /// The return is ignored if there is an error in diagnostics.
68    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
69    async fn validate<'a>(&self, diags: &mut Diagnostics, config: Self::Config<'a>) -> Option<()> {
70        _ = diags;
71        _ = config;
72        Some(())
73    }
74
75    /// Configure the provider
76    ///
77    /// # Arguments
78    ///
79    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
80    /// * `terraform_version` - Version of the Terraform binary that calls the provider
81    /// * `config` - State as declared in the Terraform file
82    ///
83    /// # Remarks
84    ///
85    /// The return is ignored if there is an error in diagnostics.
86    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
87    async fn configure<'a>(
88        &self,
89        diags: &mut Diagnostics,
90        terraform_version: String,
91        config: Self::Config<'a>,
92    ) -> Option<()> {
93        _ = diags;
94        _ = terraform_version;
95        _ = config;
96        Some(())
97    }
98
99    /// Get the schema for the provider metadata (defaults to empty)
100    ///
101    /// # Arguments
102    ///
103    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
104    ///
105    /// # Remarks
106    ///
107    /// The return is ignored if there is an error in diagnostics.
108    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
109    fn meta_schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
110        _ = diags;
111        Some(Schema {
112            version: 1,
113            block: Default::default(),
114        })
115    }
116
117    /// Get the resources of the provider
118    ///
119    /// # Arguments
120    ///
121    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the resources
122    ///
123    /// # Remarks
124    ///
125    /// The return is ignored if there is an error in diagnostics.
126    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
127    fn get_resources(
128        &self,
129        diags: &mut Diagnostics,
130    ) -> Option<HashMap<String, Box<dyn DynamicResource>>> {
131        _ = diags;
132        Some(HashMap::new())
133    }
134
135    /// Get the data sources of the provider
136    ///
137    /// # Arguments
138    ///
139    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the data sources
140    ///
141    /// # Remarks
142    ///
143    /// The return is ignored if there is an error in diagnostics.
144    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
145    fn get_data_sources(
146        &self,
147        diags: &mut Diagnostics,
148    ) -> Option<HashMap<String, Box<dyn DynamicDataSource>>> {
149        _ = diags;
150        Some(HashMap::new())
151    }
152
153    /// Get the functions of the provider
154    ///
155    /// # Arguments
156    ///
157    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the functions
158    ///
159    /// # Remarks
160    ///
161    /// The return is ignored if there is an error in diagnostics.
162    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
163    fn get_functions(
164        &self,
165        diags: &mut Diagnostics,
166    ) -> Option<HashMap<String, Box<dyn DynamicFunction>>> {
167        _ = diags;
168        Some(HashMap::new())
169    }
170}
171
172/// Trait for implementing a provider *without* automatic serialization/deserialization
173///
174/// See also: [`Provider`]
175#[async_trait]
176pub trait DynamicProvider: Send + Sync + 'static {
177    /// Get the schema of the provider
178    ///
179    /// # Arguments
180    ///
181    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
182    ///
183    /// # Remarks
184    ///
185    /// The return is ignored if there is an error in diagnostics.
186    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
187    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema>;
188
189    /// Validate the configuration of the provider
190    ///
191    /// # Arguments
192    ///
193    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
194    /// * `config` - State as declared in the Terraform file
195    ///
196    /// # Remarks
197    ///
198    /// The return is ignored if there is an error in diagnostics.
199    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
200    async fn validate(&self, diags: &mut Diagnostics, config: RawValue) -> Option<()> {
201        _ = diags;
202        _ = config;
203        Some(())
204    }
205
206    /// Configure the provider
207    ///
208    /// # Arguments
209    ///
210    /// * `diags` - Diagnostics to record warnings and errors that occured during validation
211    /// * `terraform_version` - Version of the Terraform binary that calls the provider
212    /// * `config` - State as declared in the Terraform file
213    ///
214    /// # Remarks
215    ///
216    /// The return is ignored if there is an error in diagnostics.
217    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
218    async fn configure(
219        &self,
220        diags: &mut Diagnostics,
221        terraform_version: String,
222        config: RawValue,
223    ) -> Option<()> {
224        _ = diags;
225        _ = terraform_version;
226        _ = config;
227        Some(())
228    }
229
230    /// Get the schema for the provider metadata (defaults to empty)
231    ///
232    /// # Arguments
233    ///
234    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the schema
235    ///
236    /// # Remarks
237    ///
238    /// The return is ignored if there is an error in diagnostics.
239    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
240    fn meta_schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
241        _ = diags;
242        Some(Schema {
243            version: 1,
244            block: Default::default(),
245        })
246    }
247
248    /// Get the resources of the provider
249    ///
250    /// # Arguments
251    ///
252    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the resources
253    ///
254    /// # Remarks
255    ///
256    /// The return is ignored if there is an error in diagnostics.
257    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
258    fn get_resources(
259        &self,
260        diags: &mut Diagnostics,
261    ) -> Option<HashMap<String, Box<dyn DynamicResource>>> {
262        _ = diags;
263        Some(HashMap::new())
264    }
265
266    /// Get the data sources of the provider
267    ///
268    /// # Arguments
269    ///
270    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the data sources
271    ///
272    /// # Remarks
273    ///
274    /// The return is ignored if there is an error in diagnostics.
275    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
276    fn get_data_sources(
277        &self,
278        diags: &mut Diagnostics,
279    ) -> Option<HashMap<String, Box<dyn DynamicDataSource>>> {
280        _ = diags;
281        Some(HashMap::new())
282    }
283
284    /// Get the functions of the provider
285    ///
286    /// # Arguments
287    ///
288    /// * `diags` - Diagnostics to record warnings and errors that occured when getting back the functions
289    ///
290    /// # Remarks
291    ///
292    /// The return is ignored if there is an error in diagnostics.
293    /// If the return is [`None`], an ad-hoc error is added to diagnostics.
294    fn get_functions(
295        &self,
296        diags: &mut Diagnostics,
297    ) -> Option<HashMap<String, Box<dyn DynamicFunction>>> {
298        _ = diags;
299        Some(HashMap::new())
300    }
301}
302
303#[async_trait]
304impl<T: Provider> DynamicProvider for T {
305    /// Get the schema of the provider
306    fn schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
307        <T as Provider>::schema(self, diags)
308    }
309
310    /// Validate the configuration of the provider
311    async fn validate(&self, diags: &mut Diagnostics, config: RawValue) -> Option<()> {
312        let config = config.deserialize(diags)?;
313        <T as Provider>::validate(self, diags, config).await
314    }
315
316    /// Configure the provider
317    async fn configure(
318        &self,
319        diags: &mut Diagnostics,
320        terraform_version: String,
321        config: RawValue,
322    ) -> Option<()> {
323        let config = config.deserialize(diags)?;
324        <T as Provider>::configure(self, diags, terraform_version, config).await
325    }
326
327    /// Get the schema for the provider metadata (defaults to empty)
328    fn meta_schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
329        <T as Provider>::meta_schema(self, diags)
330    }
331
332    /// Get the resources of the provider
333    fn get_resources(
334        &self,
335        diags: &mut Diagnostics,
336    ) -> Option<HashMap<String, Box<dyn DynamicResource>>> {
337        <T as Provider>::get_resources(self, diags)
338    }
339
340    /// Get the data sources of the provider
341    fn get_data_sources(
342        &self,
343        diags: &mut Diagnostics,
344    ) -> Option<HashMap<String, Box<dyn DynamicDataSource>>> {
345        <T as Provider>::get_data_sources(self, diags)
346    }
347
348    /// Get the functions of the provider
349    fn get_functions(
350        &self,
351        diags: &mut Diagnostics,
352    ) -> Option<HashMap<String, Box<dyn DynamicFunction>>> {
353        <T as Provider>::get_functions(self, diags)
354    }
355}
356
357impl<T: Provider + 'static> From<T> for Box<dyn DynamicProvider> {
358    fn from(value: T) -> Self {
359        Box::new(value)
360    }
361}