1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use strum::Display;
5use tokio::sync::mpsc::Sender;
6
7use crate::event::EngineEvent;
8
9#[derive(Debug, Default, Clone, Deserialize, Serialize)]
10#[serde(rename_all = "camelCase")]
11pub struct ResourceState {
12 pub inputs: Option<serde_json::Value>,
13 pub outputs: Option<serde_json::Value>,
14 pub urn: String,
15 #[serde(rename = "type")]
16 pub resource_type: ResourceType,
17 pub id: Option<String>,
18 pub provider: Option<String>,
19 pub parent: Option<String>,
20 pub source_position: Option<String>,
21 pub modified: Option<String>,
22 pub custom: Option<bool>,
23 pub external: Option<bool>,
24 pub created: Option<String>,
25 pub dependencies: Option<Vec<String>>,
26 pub additional_secret_outputs: Option<Vec<String>>,
27 pub property_dependencies: Option<HashMap<String, Vec<String>>>,
28
29 #[serde(flatten)]
30 pub extra_values: Option<serde_json::Value>,
31}
32
33impl ResourceState {
34 pub fn name(&self) -> String {
35 self.urn
36 .split("::")
37 .last()
38 .map(|s| s.to_string())
39 .unwrap_or_else(|| self.urn.clone())
40 }
41}
42
43#[derive(Default, Display, Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Hash)]
44pub enum ResourceType {
45 #[default]
46 Unknown,
47 #[serde(rename = "pulumi:pulumi:Stack")]
48 #[strum(serialize = "pulumi:pulumi:Stack")]
49 Stack,
50 #[serde(untagged)]
51 #[strum(serialize = "{0}")]
52 Other(String),
53}
54
55#[derive(Default, strum::Display, Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Hash)]
56#[serde(rename_all = "kebab-case")]
57pub enum Operation {
58 #[default]
59 Unknown,
60 Same,
61 Read,
62 Create,
63 Update,
64 Delete,
65 Replace,
66 Refresh,
67 Import,
68 CreateReplacement,
69 DeleteReplaced,
70 ReadReplacement,
71 Discard,
72 DiscardReplaced,
73 RemovePendingReplace,
74 ImportReplacement,
75}
76
77#[derive(Default, Debug, Clone, Deserialize, Serialize)]
78#[serde(rename_all = "camelCase")]
79pub struct StackChangeStep {
80 pub op: Operation,
81 pub urn: String,
82 pub provider: Option<String>,
83 pub new_state: Option<ResourceState>,
84 pub old_state: Option<ResourceState>,
85 #[serde(flatten)]
86 pub extra_values: Option<serde_json::Value>,
87}
88
89#[derive(Default, Debug, Clone, Deserialize, Serialize)]
90#[serde(rename_all = "camelCase")]
91pub struct StackChangeSummary {
92 pub steps: Vec<StackChangeStep>,
93 pub change_summary: Option<HashMap<Operation, usize>>,
94 pub duration: i64,
95 #[serde(flatten)]
96 pub extra_values: Option<serde_json::Value>,
97}
98
99#[derive(Debug, Clone)]
100pub struct PulumiProcessListener {
101 pub preview_tx: Option<Sender<StackChangeSummary>>,
102 pub event_tx: Sender<EngineEvent>,
103}
104
105#[derive(Debug, Clone, Default)]
106pub struct StackRefreshOptions {
107 pub skip_preview: Option<bool>,
108 pub target: Option<Vec<String>>,
109 pub target_dependents: Option<bool>,
110 pub exclude: Option<Vec<String>>,
111 pub exclude_dependents: Option<bool>,
112 pub show_secrets: Option<bool>,
113 pub continue_on_error: Option<bool>,
114}
115
116#[derive(Debug, Clone, Default)]
117pub struct StackDestroyOptions {
118 pub skip_preview: Option<bool>,
119 pub refresh: Option<bool>,
120 pub target: Option<Vec<String>>,
121 pub target_dependents: Option<bool>,
122 pub exclude: Option<Vec<String>>,
123 pub exclude_dependents: Option<bool>,
124 pub show_secrets: Option<bool>,
125 pub continue_on_error: Option<bool>,
126 pub exclude_protected: Option<bool>,
127}
128
129#[derive(Debug, Clone, Default)]
130pub struct StackUpOptions {
131 pub skip_preview: Option<bool>,
132 pub preview: Option<bool>,
133 pub refresh: Option<bool>,
134 pub replace: Option<Vec<String>>,
135 pub diff: Option<bool>,
136 pub target: Option<Vec<String>>,
137 pub target_dependents: Option<bool>,
138 pub exclude: Option<Vec<String>>,
139 pub exclude_dependents: Option<bool>,
140 pub show_secrets: Option<bool>,
141 pub continue_on_error: Option<bool>,
142 pub expect_no_changes: Option<bool>,
143 pub show_reads: Option<bool>,
144 pub show_replacement_steps: Option<bool>,
145}
146
147#[derive(Debug, Clone, Default)]
148pub struct StackPreviewOptions {
149 pub refresh: Option<bool>,
150 pub replace: Option<Vec<String>>,
151 pub diff: Option<bool>,
152 pub target: Option<Vec<String>>,
153 pub target_dependents: Option<bool>,
154 pub exclude: Option<Vec<String>>,
155 pub exclude_dependents: Option<bool>,
156 pub show_secrets: Option<bool>,
157 pub continue_on_error: Option<bool>,
158 pub expect_no_changes: Option<bool>,
159 pub show_reads: Option<bool>,
160 pub show_replacement_steps: Option<bool>,
161}
162
163#[async_trait::async_trait]
164pub trait Stack: Sized {
165 fn preview(&self, options: StackPreviewOptions) -> super::Result<StackChangeSummary>;
166 async fn preview_async(
167 &self,
168 options: StackPreviewOptions,
169 listener: PulumiProcessListener,
170 ) -> super::Result<()>;
171 async fn up(
172 &self,
173 options: StackUpOptions,
174 listener: PulumiProcessListener,
175 ) -> super::Result<()>;
176 async fn refresh(
177 &self,
178 options: StackRefreshOptions,
179 listener: PulumiProcessListener,
180 ) -> super::Result<()>;
181 async fn destroy(
182 &self,
183 options: StackDestroyOptions,
184 listener: PulumiProcessListener,
185 ) -> super::Result<()>;
186}