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 #[serde(default = "default_revision_id")]
56 pub revision_id: String,
57 #[serde(default)]
59 pub tracing_mode: Option<String>,
60 #[serde(default)]
63 pub kms_key_arn: Option<String>,
64 #[serde(default)]
66 pub ephemeral_storage_size: Option<i64>,
67 #[serde(default)]
70 pub vpc_config: Option<serde_json::Value>,
71 #[serde(default)]
73 pub snap_start: Option<serde_json::Value>,
74 #[serde(default)]
76 pub dead_letter_config_arn: Option<String>,
77 #[serde(default)]
79 pub file_system_configs: Vec<serde_json::Value>,
80 #[serde(default)]
83 pub logging_config: Option<serde_json::Value>,
84 #[serde(default)]
86 pub image_config: Option<serde_json::Value>,
87 #[serde(default)]
89 pub signing_profile_version_arn: Option<String>,
90 #[serde(default)]
92 pub signing_job_arn: Option<String>,
93 #[serde(default)]
95 pub runtime_version_config: Option<serde_json::Value>,
96 #[serde(default)]
99 pub master_arn: Option<String>,
100 #[serde(default)]
104 pub state_reason: Option<String>,
105 #[serde(default)]
108 pub state_reason_code: Option<String>,
109 #[serde(default)]
113 pub durable_config: Option<serde_json::Value>,
114 #[serde(default)]
117 pub last_update_status_reason: Option<String>,
118 #[serde(default)]
121 pub last_update_status_reason_code: Option<String>,
122}
123
124fn default_revision_id() -> String {
125 uuid::Uuid::new_v4().to_string()
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct AttachedLayer {
130 pub arn: String,
131 #[serde(default)]
132 pub code_size: i64,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct EventSourceMapping {
137 pub uuid: String,
138 pub function_arn: String,
139 pub event_source_arn: String,
140 pub batch_size: i64,
141 pub enabled: bool,
142 pub state: String,
143 pub last_modified: DateTime<Utc>,
144 #[serde(default)]
149 pub filter_patterns: Vec<String>,
150 #[serde(default)]
153 pub maximum_batching_window_in_seconds: Option<i64>,
154 #[serde(default)]
157 pub starting_position: Option<String>,
158 #[serde(default)]
161 pub starting_position_timestamp: Option<f64>,
162 #[serde(default)]
164 pub parallelization_factor: Option<i64>,
165 #[serde(default)]
168 pub function_response_types: Vec<String>,
169 #[serde(default)]
173 pub kms_key_arn: Option<String>,
174 #[serde(default)]
178 pub metrics_config: Option<serde_json::Value>,
179 #[serde(default)]
182 pub destination_config: Option<serde_json::Value>,
183 #[serde(default)]
186 pub maximum_retry_attempts: Option<i64>,
187 #[serde(default)]
189 pub maximum_record_age_in_seconds: Option<i64>,
190 #[serde(default)]
193 pub bisect_batch_on_function_error: Option<bool>,
194 #[serde(default)]
196 pub tumbling_window_in_seconds: Option<i64>,
197 #[serde(default)]
199 pub topics: Vec<String>,
200 #[serde(default)]
202 pub queues: Vec<String>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct LambdaInvocation {
208 pub function_arn: String,
209 pub payload: String,
210 pub timestamp: DateTime<Utc>,
211 pub source: String,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct LambdaState {
216 pub account_id: String,
217 pub region: String,
218 #[serde(default)]
219 pub functions: BTreeMap<String, LambdaFunction>,
220 #[serde(default)]
221 pub event_source_mappings: BTreeMap<String, EventSourceMapping>,
222 #[serde(default, skip)]
224 pub invocations: Vec<LambdaInvocation>,
225 #[serde(default)]
227 pub aliases: BTreeMap<String, FunctionAlias>,
228 #[serde(default)]
230 pub function_versions: BTreeMap<String, Vec<String>>,
231 #[serde(default)]
235 pub function_version_snapshots: BTreeMap<String, BTreeMap<String, LambdaFunction>>,
236 #[serde(default)]
238 pub layers: BTreeMap<String, Layer>,
239 #[serde(default)]
241 pub function_url_configs: BTreeMap<String, FunctionUrlConfig>,
242 #[serde(default)]
244 pub function_concurrency: BTreeMap<String, i64>,
245 #[serde(default)]
247 pub provisioned_concurrency: BTreeMap<String, ProvisionedConcurrencyConfig>,
248 #[serde(default)]
250 pub code_signing_configs: BTreeMap<String, CodeSigningConfig>,
251 #[serde(default)]
253 pub function_code_signing: BTreeMap<String, String>,
254 #[serde(default)]
256 pub event_invoke_configs: BTreeMap<String, EventInvokeConfig>,
257 #[serde(default)]
259 pub runtime_management: BTreeMap<String, RuntimeManagementConfig>,
260 #[serde(default)]
262 pub scaling_configs: BTreeMap<String, FunctionScalingConfig>,
263 #[serde(default)]
265 pub recursion_configs: BTreeMap<String, String>,
266 #[serde(default)]
268 pub account_settings: Option<AccountSettings>,
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct FunctionAlias {
273 pub alias_arn: String,
274 pub name: String,
275 pub function_version: String,
276 pub description: String,
277 pub revision_id: String,
278 pub routing_config: Option<serde_json::Value>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct Layer {
283 pub layer_name: String,
284 pub layer_arn: String,
285 pub versions: Vec<LayerVersion>,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct LayerVersion {
290 pub version: i64,
291 pub layer_version_arn: String,
292 pub description: String,
293 pub created_date: DateTime<Utc>,
294 pub compatible_runtimes: Vec<String>,
295 pub license_info: String,
296 pub policy: Option<String>,
297 #[serde(default)]
300 pub code_zip: Option<Vec<u8>>,
301 #[serde(default)]
302 pub code_sha256: String,
303 #[serde(default)]
304 pub code_size: i64,
305 #[serde(default)]
309 pub compatible_architectures: Vec<String>,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
313pub struct FunctionUrlConfig {
314 pub function_arn: String,
315 pub function_url: String,
316 pub auth_type: String,
317 pub cors: Option<serde_json::Value>,
318 pub creation_time: DateTime<Utc>,
319 pub last_modified_time: DateTime<Utc>,
320 pub invoke_mode: String,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct ProvisionedConcurrencyConfig {
325 pub requested: i64,
326 pub allocated: i64,
327 pub status: String,
328 pub last_modified: DateTime<Utc>,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct CodeSigningConfig {
333 pub csc_id: String,
334 pub csc_arn: String,
335 pub description: String,
336 pub allowed_publishers: Vec<String>,
337 pub untrusted_artifact_action: String,
338 pub last_modified: DateTime<Utc>,
339}
340
341#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct EventInvokeConfig {
343 pub function_arn: String,
344 pub maximum_event_age: i64,
345 pub maximum_retry_attempts: i64,
346 #[serde(default)]
356 pub destination_config: Option<serde_json::Value>,
357 pub last_modified: DateTime<Utc>,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct RuntimeManagementConfig {
362 pub update_runtime_on: String,
363 pub runtime_version_arn: String,
364}
365
366#[derive(Debug, Clone, Serialize, Deserialize, Default)]
367pub struct FunctionScalingConfig {
368 pub min_execution_environments: Option<i64>,
373 pub max_execution_environments: Option<i64>,
376}
377
378#[derive(Debug, Clone, Serialize, Deserialize, Default)]
379pub struct AccountSettings {
380 pub concurrent_executions: i64,
381 pub code_size_zipped: i64,
382 pub code_size_unzipped: i64,
383 pub total_code_size: i64,
384}
385
386impl LambdaState {
387 pub fn new(account_id: &str, region: &str) -> Self {
388 Self {
389 account_id: account_id.to_string(),
390 region: region.to_string(),
391 functions: BTreeMap::new(),
392 event_source_mappings: BTreeMap::new(),
393 invocations: Vec::new(),
394 aliases: BTreeMap::new(),
395 function_versions: BTreeMap::new(),
396 function_version_snapshots: BTreeMap::new(),
397 layers: BTreeMap::new(),
398 function_url_configs: BTreeMap::new(),
399 function_concurrency: BTreeMap::new(),
400 provisioned_concurrency: BTreeMap::new(),
401 code_signing_configs: BTreeMap::new(),
402 function_code_signing: BTreeMap::new(),
403 event_invoke_configs: BTreeMap::new(),
404 runtime_management: BTreeMap::new(),
405 scaling_configs: BTreeMap::new(),
406 recursion_configs: BTreeMap::new(),
407 account_settings: None,
408 }
409 }
410
411 pub fn reset(&mut self) {
412 self.functions.clear();
413 self.event_source_mappings.clear();
414 self.invocations.clear();
415 self.aliases.clear();
416 self.function_versions.clear();
417 self.function_version_snapshots.clear();
418 self.layers.clear();
419 self.function_url_configs.clear();
420 self.function_concurrency.clear();
421 self.provisioned_concurrency.clear();
422 self.code_signing_configs.clear();
423 self.function_code_signing.clear();
424 self.event_invoke_configs.clear();
425 self.runtime_management.clear();
426 self.scaling_configs.clear();
427 self.recursion_configs.clear();
428 self.account_settings = None;
429 }
430}
431
432pub type SharedLambdaState =
433 Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<LambdaState>>>;
434
435impl fakecloud_core::multi_account::AccountState for LambdaState {
436 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
437 Self::new(account_id, region)
438 }
439}
440
441pub const LAMBDA_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
442
443#[derive(Debug, Serialize, Deserialize)]
444pub struct LambdaSnapshot {
445 pub schema_version: u32,
446 #[serde(default)]
447 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<LambdaState>>,
448 #[serde(default)]
449 pub state: Option<LambdaState>,
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455
456 #[test]
457 fn new_has_empty_collections() {
458 let state = LambdaState::new("123456789012", "us-east-1");
459 assert_eq!(state.account_id, "123456789012");
460 assert_eq!(state.region, "us-east-1");
461 assert!(state.functions.is_empty());
462 assert!(state.event_source_mappings.is_empty());
463 assert!(state.invocations.is_empty());
464 }
465
466 #[test]
467 fn reset_clears_collections() {
468 let mut state = LambdaState::new("123456789012", "us-east-1");
469 state.invocations.push(LambdaInvocation {
470 function_arn: "arn".to_string(),
471 payload: "p".to_string(),
472 timestamp: Utc::now(),
473 source: "s".to_string(),
474 });
475 state.reset();
476 assert!(state.invocations.is_empty());
477 }
478}