1use chrono::{DateTime, Utc};
2use parking_lot::RwLock;
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5use std::sync::Arc;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct LambdaFunction {
9 pub function_name: String,
10 pub function_arn: String,
11 pub runtime: String,
12 pub role: String,
13 pub handler: String,
14 pub description: String,
15 pub timeout: i64,
16 pub memory_size: i64,
17 pub code_sha256: String,
18 pub code_size: i64,
19 pub version: String,
20 pub last_modified: DateTime<Utc>,
21 pub tags: BTreeMap<String, String>,
22 pub environment: BTreeMap<String, String>,
23 pub architectures: Vec<String>,
24 pub package_type: String,
25 pub code_zip: Option<Vec<u8>>,
26 #[serde(default)]
30 pub image_uri: Option<String>,
31 pub policy: Option<String>,
40 #[serde(default)]
48 pub layers: Vec<AttachedLayer>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct AttachedLayer {
53 pub arn: String,
54 #[serde(default)]
55 pub code_size: i64,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct EventSourceMapping {
60 pub uuid: String,
61 pub function_arn: String,
62 pub event_source_arn: String,
63 pub batch_size: i64,
64 pub enabled: bool,
65 pub state: String,
66 pub last_modified: DateTime<Utc>,
67 #[serde(default)]
72 pub filter_patterns: Vec<String>,
73 #[serde(default)]
76 pub maximum_batching_window_in_seconds: Option<i64>,
77 #[serde(default)]
80 pub starting_position: Option<String>,
81 #[serde(default)]
84 pub starting_position_timestamp: Option<f64>,
85 #[serde(default)]
87 pub parallelization_factor: Option<i64>,
88 #[serde(default)]
91 pub function_response_types: Vec<String>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct LambdaInvocation {
97 pub function_arn: String,
98 pub payload: String,
99 pub timestamp: DateTime<Utc>,
100 pub source: String,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct LambdaState {
105 pub account_id: String,
106 pub region: String,
107 #[serde(default)]
108 pub functions: BTreeMap<String, LambdaFunction>,
109 #[serde(default)]
110 pub event_source_mappings: BTreeMap<String, EventSourceMapping>,
111 #[serde(default, skip)]
113 pub invocations: Vec<LambdaInvocation>,
114 #[serde(default)]
116 pub aliases: BTreeMap<String, FunctionAlias>,
117 #[serde(default)]
119 pub function_versions: BTreeMap<String, Vec<String>>,
120 #[serde(default)]
122 pub layers: BTreeMap<String, Layer>,
123 #[serde(default)]
125 pub function_url_configs: BTreeMap<String, FunctionUrlConfig>,
126 #[serde(default)]
128 pub function_concurrency: BTreeMap<String, i64>,
129 #[serde(default)]
131 pub provisioned_concurrency: BTreeMap<String, ProvisionedConcurrencyConfig>,
132 #[serde(default)]
134 pub code_signing_configs: BTreeMap<String, CodeSigningConfig>,
135 #[serde(default)]
137 pub function_code_signing: BTreeMap<String, String>,
138 #[serde(default)]
140 pub event_invoke_configs: BTreeMap<String, EventInvokeConfig>,
141 #[serde(default)]
143 pub runtime_management: BTreeMap<String, RuntimeManagementConfig>,
144 #[serde(default)]
146 pub scaling_configs: BTreeMap<String, FunctionScalingConfig>,
147 #[serde(default)]
149 pub recursion_configs: BTreeMap<String, String>,
150 #[serde(default)]
152 pub tags: BTreeMap<String, Vec<(String, String)>>,
153 #[serde(default)]
155 pub capacity_providers: BTreeMap<String, CapacityProvider>,
156 #[serde(default)]
158 pub durable_executions: BTreeMap<String, DurableExecution>,
159 #[serde(default)]
161 pub account_settings: Option<AccountSettings>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct FunctionAlias {
166 pub alias_arn: String,
167 pub name: String,
168 pub function_version: String,
169 pub description: String,
170 pub revision_id: String,
171 pub routing_config: Option<serde_json::Value>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct Layer {
176 pub layer_name: String,
177 pub layer_arn: String,
178 pub versions: Vec<LayerVersion>,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct LayerVersion {
183 pub version: i64,
184 pub layer_version_arn: String,
185 pub description: String,
186 pub created_date: DateTime<Utc>,
187 pub compatible_runtimes: Vec<String>,
188 pub license_info: String,
189 pub policy: Option<String>,
190 #[serde(default)]
193 pub code_zip: Option<Vec<u8>>,
194 #[serde(default)]
195 pub code_sha256: String,
196 #[serde(default)]
197 pub code_size: i64,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct FunctionUrlConfig {
202 pub function_arn: String,
203 pub function_url: String,
204 pub auth_type: String,
205 pub cors: Option<serde_json::Value>,
206 pub creation_time: DateTime<Utc>,
207 pub last_modified_time: DateTime<Utc>,
208 pub invoke_mode: String,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct ProvisionedConcurrencyConfig {
213 pub requested: i64,
214 pub allocated: i64,
215 pub status: String,
216 pub last_modified: DateTime<Utc>,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct CodeSigningConfig {
221 pub csc_id: String,
222 pub csc_arn: String,
223 pub description: String,
224 pub allowed_publishers: Vec<String>,
225 pub untrusted_artifact_action: String,
226 pub last_modified: DateTime<Utc>,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct EventInvokeConfig {
231 pub function_arn: String,
232 pub maximum_event_age: i64,
233 pub maximum_retry_attempts: i64,
234 pub destination_config: serde_json::Value,
235 pub last_modified: DateTime<Utc>,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct RuntimeManagementConfig {
240 pub update_runtime_on: String,
241 pub runtime_version_arn: String,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct FunctionScalingConfig {
246 pub maximum_concurrency: i64,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct CapacityProvider {
251 pub name: String,
252 pub arn: String,
253 pub status: String,
254 pub created: DateTime<Utc>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct DurableExecution {
259 pub id: String,
260 pub function_arn: String,
261 pub status: String,
262 pub started: DateTime<Utc>,
263 pub stopped: Option<DateTime<Utc>>,
264 pub history: Vec<serde_json::Value>,
265 pub state: serde_json::Value,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize, Default)]
269pub struct AccountSettings {
270 pub concurrent_executions: i64,
271 pub code_size_zipped: i64,
272 pub code_size_unzipped: i64,
273 pub total_code_size: i64,
274}
275
276impl LambdaState {
277 pub fn new(account_id: &str, region: &str) -> Self {
278 Self {
279 account_id: account_id.to_string(),
280 region: region.to_string(),
281 functions: BTreeMap::new(),
282 event_source_mappings: BTreeMap::new(),
283 invocations: Vec::new(),
284 aliases: BTreeMap::new(),
285 function_versions: BTreeMap::new(),
286 layers: BTreeMap::new(),
287 function_url_configs: BTreeMap::new(),
288 function_concurrency: BTreeMap::new(),
289 provisioned_concurrency: BTreeMap::new(),
290 code_signing_configs: BTreeMap::new(),
291 function_code_signing: BTreeMap::new(),
292 event_invoke_configs: BTreeMap::new(),
293 runtime_management: BTreeMap::new(),
294 scaling_configs: BTreeMap::new(),
295 recursion_configs: BTreeMap::new(),
296 tags: BTreeMap::new(),
297 capacity_providers: BTreeMap::new(),
298 durable_executions: BTreeMap::new(),
299 account_settings: None,
300 }
301 }
302
303 pub fn reset(&mut self) {
304 self.functions.clear();
305 self.event_source_mappings.clear();
306 self.invocations.clear();
307 self.aliases.clear();
308 self.function_versions.clear();
309 self.layers.clear();
310 self.function_url_configs.clear();
311 self.function_concurrency.clear();
312 self.provisioned_concurrency.clear();
313 self.code_signing_configs.clear();
314 self.function_code_signing.clear();
315 self.event_invoke_configs.clear();
316 self.runtime_management.clear();
317 self.scaling_configs.clear();
318 self.recursion_configs.clear();
319 self.tags.clear();
320 self.capacity_providers.clear();
321 self.durable_executions.clear();
322 self.account_settings = None;
323 }
324}
325
326pub type SharedLambdaState =
327 Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<LambdaState>>>;
328
329impl fakecloud_core::multi_account::AccountState for LambdaState {
330 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
331 Self::new(account_id, region)
332 }
333}
334
335pub const LAMBDA_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
336
337#[derive(Debug, Serialize, Deserialize)]
338pub struct LambdaSnapshot {
339 pub schema_version: u32,
340 #[serde(default)]
341 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<LambdaState>>,
342 #[serde(default)]
343 pub state: Option<LambdaState>,
344}
345
346#[cfg(test)]
347mod tests {
348 use super::*;
349
350 #[test]
351 fn new_has_empty_collections() {
352 let state = LambdaState::new("123456789012", "us-east-1");
353 assert_eq!(state.account_id, "123456789012");
354 assert_eq!(state.region, "us-east-1");
355 assert!(state.functions.is_empty());
356 assert!(state.event_source_mappings.is_empty());
357 assert!(state.invocations.is_empty());
358 }
359
360 #[test]
361 fn reset_clears_collections() {
362 let mut state = LambdaState::new("123456789012", "us-east-1");
363 state.invocations.push(LambdaInvocation {
364 function_arn: "arn".to_string(),
365 payload: "p".to_string(),
366 timestamp: Utc::now(),
367 source: "s".to_string(),
368 });
369 state.reset();
370 assert!(state.invocations.is_empty());
371 }
372}