1use pulumi_gestalt_model::ToPulumiValue;
2
3pub type PulumiAny = pulumi_gestalt_model::PulumiValueMiddleware;
4
5#[macro_export]
10macro_rules! pulumi_any {
11 ($($tt:tt)+) => {
12 $crate::pulumi_any_v2_internal!($($tt)+)
13 };
14}
15
16#[doc(hidden)]
17#[macro_export]
18macro_rules! pulumi_any_v2_internal {
19 (null) => {
20 $crate::__private::pulumi_gestalt_model::__private::pulumi_value_middleware(
21 $crate::__private::pulumi_gestalt_model::PulumiValueContent::None,
22 )
23 };
24 ([$($tt:tt)*]) => {
25 $crate::pulumi_any_v2_internal_array!([] $($tt)*)
26 };
27 ({$($tt:tt)*}) => {
28 $crate::pulumi_any_v2_internal_object!([] $($tt)*)
29 };
30 ($other:expr) => {
31 $crate::__private::pulumi_gestalt_model::__private::to_pulumi_value_middleware($other)
32 };
33}
34
35#[doc(hidden)]
36#[macro_export]
37macro_rules! pulumi_any_v2_internal_array {
38 ([$($elems:expr,)*]) => {
39 $crate::__private::pulumi_gestalt_model::__private::pulumi_value_middleware_array(
40 vec![$($elems,)*]
41 )
42 };
43 ([$($elems:expr,)*] , $($rest:tt)*) => {
44 $crate::pulumi_any_v2_internal_array!([$($elems,)*] $($rest)*)
45 };
46 ([$($elems:expr,)*] null , $($rest:tt)*) => {
47 $crate::pulumi_any_v2_internal_array!(
48 [
49 $($elems,)*
50 $crate::pulumi_any_v2_internal!(null),
51 ]
52 $($rest)*
53 )
54 };
55 ([$($elems:expr,)*] [$($inner:tt)*] , $($rest:tt)*) => {
56 $crate::pulumi_any_v2_internal_array!(
57 [
58 $($elems,)*
59 $crate::pulumi_any_v2_internal!([$($inner)*]),
60 ]
61 $($rest)*
62 )
63 };
64 ([$($elems:expr,)*] {$($inner:tt)*} , $($rest:tt)*) => {
65 $crate::pulumi_any_v2_internal_array!(
66 [
67 $($elems,)*
68 $crate::pulumi_any_v2_internal!({$($inner)*}),
69 ]
70 $($rest)*
71 )
72 };
73 ([$($elems:expr,)*] $next:expr , $($rest:tt)*) => {
74 $crate::pulumi_any_v2_internal_array!(
75 [
76 $($elems,)*
77 $crate::pulumi_any_v2_internal!($next),
78 ]
79 $($rest)*
80 )
81 };
82 ([$($elems:expr,)*] null) => {
83 $crate::pulumi_any_v2_internal_array!(
84 [
85 $($elems,)*
86 $crate::pulumi_any_v2_internal!(null),
87 ]
88 )
89 };
90 ([$($elems:expr,)*] [$($inner:tt)*]) => {
91 $crate::pulumi_any_v2_internal_array!(
92 [
93 $($elems,)*
94 $crate::pulumi_any_v2_internal!([$($inner)*]),
95 ]
96 )
97 };
98 ([$($elems:expr,)*] {$($inner:tt)*}) => {
99 $crate::pulumi_any_v2_internal_array!(
100 [
101 $($elems,)*
102 $crate::pulumi_any_v2_internal!({$($inner)*}),
103 ]
104 )
105 };
106 ([$($elems:expr,)*] $next:expr) => {
107 $crate::pulumi_any_v2_internal_array!(
108 [
109 $($elems,)*
110 $crate::pulumi_any_v2_internal!($next),
111 ]
112 )
113 };
114}
115
116#[doc(hidden)]
117#[macro_export]
118macro_rules! pulumi_any_v2_internal_object {
119 ([$($fields:expr,)*]) => {
120 $crate::__private::pulumi_gestalt_model::__private::pulumi_value_middleware_object(
121 vec![$($fields,)*]
122 )
123 };
124 ([$($fields:expr,)*] , $($rest:tt)*) => {
125 $crate::pulumi_any_v2_internal_object!([$($fields,)*] $($rest)*)
126 };
127 ([$($fields:expr,)*] $key:tt : null , $($rest:tt)*) => {
128 $crate::pulumi_any_v2_internal_object!(
129 [
130 $($fields,)*
131 (
132 ::std::convert::Into::<::std::string::String>::into($key),
133 $crate::pulumi_any_v2_internal!(null),
134 ),
135 ]
136 $($rest)*
137 )
138 };
139 ([$($fields:expr,)*] $key:tt : [$($inner:tt)*] , $($rest:tt)*) => {
140 $crate::pulumi_any_v2_internal_object!(
141 [
142 $($fields,)*
143 (
144 ::std::convert::Into::<::std::string::String>::into($key),
145 $crate::pulumi_any_v2_internal!([$($inner)*]),
146 ),
147 ]
148 $($rest)*
149 )
150 };
151 ([$($fields:expr,)*] $key:tt : {$($inner:tt)*} , $($rest:tt)*) => {
152 $crate::pulumi_any_v2_internal_object!(
153 [
154 $($fields,)*
155 (
156 ::std::convert::Into::<::std::string::String>::into($key),
157 $crate::pulumi_any_v2_internal!({$($inner)*}),
158 ),
159 ]
160 $($rest)*
161 )
162 };
163 ([$($fields:expr,)*] $key:tt : $value:expr , $($rest:tt)*) => {
164 $crate::pulumi_any_v2_internal_object!(
165 [
166 $($fields,)*
167 (
168 ::std::convert::Into::<::std::string::String>::into($key),
169 $crate::pulumi_any_v2_internal!($value),
170 ),
171 ]
172 $($rest)*
173 )
174 };
175 ([$($fields:expr,)*] $key:tt : null) => {
176 $crate::pulumi_any_v2_internal_object!(
177 [
178 $($fields,)*
179 (
180 ::std::convert::Into::<::std::string::String>::into($key),
181 $crate::pulumi_any_v2_internal!(null),
182 ),
183 ]
184 )
185 };
186 ([$($fields:expr,)*] $key:tt : [$($inner:tt)*]) => {
187 $crate::pulumi_any_v2_internal_object!(
188 [
189 $($fields,)*
190 (
191 ::std::convert::Into::<::std::string::String>::into($key),
192 $crate::pulumi_any_v2_internal!([$($inner)*]),
193 ),
194 ]
195 )
196 };
197 ([$($fields:expr,)*] $key:tt : {$($inner:tt)*}) => {
198 $crate::pulumi_any_v2_internal_object!(
199 [
200 $($fields,)*
201 (
202 ::std::convert::Into::<::std::string::String>::into($key),
203 $crate::pulumi_any_v2_internal!({$($inner)*}),
204 ),
205 ]
206 )
207 };
208 ([$($fields:expr,)*] $key:tt : $value:expr) => {
209 $crate::pulumi_any_v2_internal_object!(
210 [
211 $($fields,)*
212 (
213 ::std::convert::Into::<::std::string::String>::into($key),
214 $crate::pulumi_any_v2_internal!($value),
215 ),
216 ]
217 )
218 };
219}
220
221pub trait ToPulumiAny {
222 fn to_pulumi_any(self) -> PulumiAny;
223}
224
225impl<T> ToPulumiAny for T
226where
227 T: ToPulumiValue + Send + Sync + 'static,
228{
229 fn to_pulumi_any(self) -> PulumiAny {
230 pulumi_gestalt_model::__private::to_pulumi_value_middleware(self)
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use super::ToPulumiAny;
237 use pulumi_gestalt_model::__private::futures::executor::block_on;
238 use pulumi_gestalt_model::{
239 Output as ModelOutput, PulumiValue, PulumiValueContent, ToPulumiValue,
240 };
241 use std::collections::HashSet;
242
243 struct CustomToPulumiValue {
244 id: i32,
245 }
246
247 impl ToPulumiValue for CustomToPulumiValue {
248 fn to_pulumi_value(&self) -> impl std::future::Future<Output = PulumiValue> + Send {
249 let id = self.id;
250 std::future::ready(PulumiValue {
251 content: PulumiValueContent::Object(vec![(
252 "custom-id".to_string(),
253 pv(PulumiValueContent::Integer(id + 1000)),
254 )]),
255 secret: false,
256 dependencies: HashSet::new(),
257 })
258 }
259 }
260
261 fn pv(content: PulumiValueContent) -> PulumiValue {
262 PulumiValue {
263 content,
264 secret: false,
265 dependencies: HashSet::new(),
266 }
267 }
268
269 fn pvs(content: PulumiValueContent) -> PulumiValue {
270 PulumiValue {
271 content,
272 secret: true,
273 dependencies: HashSet::new(),
274 }
275 }
276
277 #[test]
278 fn to_pulumi_any_converts_plain_value() {
279 let pulumi_any = "demo".to_pulumi_any();
280 let decoded = block_on(pulumi_any.to_pulumi_value());
281 assert_eq!(decoded, pv(PulumiValueContent::String("demo".to_string())));
282 }
283
284 #[test]
285 fn pulumi_any_macro_scalar() {
286 let integer = block_on(pulumi_any!(42).to_pulumi_value());
287 assert_eq!(integer, pv(PulumiValueContent::Integer(42)));
288
289 let float = block_on(pulumi_any!(1.5f64).to_pulumi_value());
290 assert_eq!(float, pv(PulumiValueContent::Number(1.5)));
291
292 let boolean = block_on(pulumi_any!(true).to_pulumi_value());
293 assert_eq!(boolean, pv(PulumiValueContent::Boolean(true)));
294
295 let string = block_on(pulumi_any!("hello").to_pulumi_value());
296 assert_eq!(string, pv(PulumiValueContent::String("hello".to_string())));
297 }
298
299 #[test]
300 fn pulumi_any_macro_array_and_object() {
301 let array = block_on(pulumi_any!([1, 2, 3]).to_pulumi_value());
302 assert_eq!(
303 array,
304 pv(PulumiValueContent::Array(vec![
305 pv(PulumiValueContent::Integer(1)),
306 pv(PulumiValueContent::Integer(2)),
307 pv(PulumiValueContent::Integer(3)),
308 ]))
309 );
310
311 let object = block_on(pulumi_any!({"name": "macro_test", "count": 5}).to_pulumi_value());
312 assert_eq!(
313 object,
314 pv(PulumiValueContent::Object(vec![
315 ("count".to_string(), pv(PulumiValueContent::Integer(5))),
316 (
317 "name".to_string(),
318 pv(PulumiValueContent::String("macro_test".to_string()))
319 ),
320 ]))
321 );
322 }
323
324 #[test]
325 fn pulumi_any_macro_nested_and_trailing_commas() {
326 let value = block_on(
327 pulumi_any!({
328 "items": [
329 1,
330 {"name": "a",},
331 ],
332 "ok": true,
333 })
334 .to_pulumi_value(),
335 );
336
337 assert_eq!(
338 value,
339 pv(PulumiValueContent::Object(vec![
340 (
341 "items".to_string(),
342 pv(PulumiValueContent::Array(vec![
343 pv(PulumiValueContent::Integer(1)),
344 pv(PulumiValueContent::Object(vec![(
345 "name".to_string(),
346 pv(PulumiValueContent::String("a".to_string())),
347 )])),
348 ])),
349 ),
350 ("ok".to_string(), pv(PulumiValueContent::Boolean(true))),
351 ]))
352 );
353 }
354
355 #[test]
356 fn pulumi_any_macro_nested_model_outputs() {
357 let value = block_on(
358 pulumi_any!({
359 "known": ModelOutput::new(7i32),
360 "secret": ModelOutput::new_secret("sensitive"),
361 "unknown": ModelOutput::<i32>::new_nothing(),
362 "nested": [ModelOutput::new(true)],
363 })
364 .to_pulumi_value(),
365 );
366
367 assert_eq!(
368 value,
369 pvs(PulumiValueContent::Object(vec![
370 ("known".to_string(), pv(PulumiValueContent::Integer(7))),
371 (
372 "nested".to_string(),
373 pv(PulumiValueContent::Array(vec![pv(
374 PulumiValueContent::Boolean(true)
375 )])),
376 ),
377 (
378 "secret".to_string(),
379 pvs(PulumiValueContent::String("sensitive".to_string())),
380 ),
381 ("unknown".to_string(), pv(PulumiValueContent::Nothing)),
382 ]))
383 );
384 }
385
386 #[test]
387 fn pulumi_any_macro_object_sorts_keys() {
388 let value = block_on(
389 pulumi_any!({
390 "z": 1,
391 "a": 2,
392 })
393 .to_pulumi_value(),
394 );
395
396 assert_eq!(
397 value,
398 pv(PulumiValueContent::Object(vec![
399 ("a".to_string(), pv(PulumiValueContent::Integer(2))),
400 ("z".to_string(), pv(PulumiValueContent::Integer(1))),
401 ]))
402 );
403 }
404
405 #[test]
406 fn pulumi_any_macro_object_last_wins_for_duplicate_keys() {
407 let value = block_on(
408 pulumi_any!({
409 "a": 1,
410 "a": 2,
411 "b": 3,
412 })
413 .to_pulumi_value(),
414 );
415
416 assert_eq!(
417 value,
418 pv(PulumiValueContent::Object(vec![
419 ("a".to_string(), pv(PulumiValueContent::Integer(2))),
420 ("b".to_string(), pv(PulumiValueContent::Integer(3))),
421 ]))
422 );
423 }
424
425 #[test]
426 fn pulumi_any_macro_array_propagates_secret_from_nested_output() {
427 let value = block_on(
428 pulumi_any!([ModelOutput::new(1i32), ModelOutput::new_secret(2i32),]).to_pulumi_value(),
429 );
430
431 assert_eq!(
432 value,
433 pvs(PulumiValueContent::Array(vec![
434 pv(PulumiValueContent::Integer(1)),
435 pvs(PulumiValueContent::Integer(2)),
436 ]))
437 );
438 }
439
440 #[test]
441 fn pulumi_any_macro_uses_custom_to_pulumi_value_impl() {
442 let value = block_on(
443 pulumi_any!({
444 "custom": CustomToPulumiValue { id: 7 },
445 })
446 .to_pulumi_value(),
447 );
448
449 assert_eq!(
450 value,
451 pv(PulumiValueContent::Object(vec![(
452 "custom".to_string(),
453 pv(PulumiValueContent::Object(vec![(
454 "custom-id".to_string(),
455 pv(PulumiValueContent::Integer(1007)),
456 )])),
457 )]))
458 );
459 }
460}