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 #[serde(default)]
207 pub source_access_configurations: Vec<serde_json::Value>,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct LambdaInvocation {
213 pub function_arn: String,
214 pub payload: String,
215 pub timestamp: DateTime<Utc>,
216 pub source: String,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct LambdaState {
221 pub account_id: String,
222 pub region: String,
223 #[serde(default)]
224 pub functions: BTreeMap<String, LambdaFunction>,
225 #[serde(default)]
226 pub event_source_mappings: BTreeMap<String, EventSourceMapping>,
227 #[serde(default, skip)]
229 pub invocations: Vec<LambdaInvocation>,
230 #[serde(default)]
232 pub aliases: BTreeMap<String, FunctionAlias>,
233 #[serde(default)]
235 pub function_versions: BTreeMap<String, Vec<String>>,
236 #[serde(default)]
240 pub function_version_snapshots: BTreeMap<String, BTreeMap<String, LambdaFunction>>,
241 #[serde(default)]
243 pub layers: BTreeMap<String, Layer>,
244 #[serde(default)]
246 pub function_url_configs: BTreeMap<String, FunctionUrlConfig>,
247 #[serde(default)]
249 pub function_concurrency: BTreeMap<String, i64>,
250 #[serde(default)]
252 pub provisioned_concurrency: BTreeMap<String, ProvisionedConcurrencyConfig>,
253 #[serde(default)]
255 pub code_signing_configs: BTreeMap<String, CodeSigningConfig>,
256 #[serde(default)]
258 pub function_code_signing: BTreeMap<String, String>,
259 #[serde(default)]
261 pub event_invoke_configs: BTreeMap<String, EventInvokeConfig>,
262 #[serde(default)]
264 pub runtime_management: BTreeMap<String, RuntimeManagementConfig>,
265 #[serde(default)]
267 pub scaling_configs: BTreeMap<String, FunctionScalingConfig>,
268 #[serde(default)]
270 pub recursion_configs: BTreeMap<String, String>,
271 #[serde(default)]
273 pub account_settings: Option<AccountSettings>,
274 #[serde(default)]
276 pub capacity_providers: BTreeMap<String, CapacityProvider>,
277 #[serde(default)]
279 pub durable_executions: BTreeMap<String, DurableExecution>,
280 #[serde(default)]
283 pub durable_execution_callbacks: BTreeMap<String, DurableExecutionCallback>,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct CapacityProvider {
288 pub name: String,
289 pub arn: String,
290 pub state: String,
291 pub vpc_config: serde_json::Value,
292 pub permissions_config: serde_json::Value,
293 pub instance_requirements: Option<serde_json::Value>,
294 pub scaling_config: Option<serde_json::Value>,
295 pub kms_key_arn: Option<String>,
296 pub tags: BTreeMap<String, String>,
297 pub last_modified: DateTime<Utc>,
298 #[serde(default)]
304 pub function_versions: Vec<String>,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct DurableExecution {
309 pub arn: String,
310 pub function_name: String,
311 pub function_arn: String,
312 pub status: String,
313 pub input: serde_json::Value,
314 pub started_at: DateTime<Utc>,
315 pub stopped_at: Option<DateTime<Utc>>,
316 pub last_modified: DateTime<Utc>,
317 pub history: Vec<serde_json::Value>,
318 pub state: serde_json::Value,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct DurableExecutionCallback {
323 pub callback_id: String,
324 pub execution_arn: String,
325 pub outcome: String,
326 pub recorded_at: DateTime<Utc>,
327}
328
329#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct FunctionAlias {
331 pub alias_arn: String,
332 pub name: String,
333 pub function_version: String,
334 pub description: String,
335 pub revision_id: String,
336 pub routing_config: Option<serde_json::Value>,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct Layer {
341 pub layer_name: String,
342 pub layer_arn: String,
343 pub versions: Vec<LayerVersion>,
344}
345
346#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct LayerVersion {
348 pub version: i64,
349 pub layer_version_arn: String,
350 pub description: String,
351 pub created_date: DateTime<Utc>,
352 pub compatible_runtimes: Vec<String>,
353 pub license_info: String,
354 pub policy: Option<String>,
355 #[serde(default)]
358 pub code_zip: Option<Vec<u8>>,
359 #[serde(default)]
360 pub code_sha256: String,
361 #[serde(default)]
362 pub code_size: i64,
363 #[serde(default)]
367 pub compatible_architectures: Vec<String>,
368}
369
370#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct FunctionUrlConfig {
372 pub function_arn: String,
373 pub function_url: String,
374 pub auth_type: String,
375 pub cors: Option<serde_json::Value>,
376 pub creation_time: DateTime<Utc>,
377 pub last_modified_time: DateTime<Utc>,
378 pub invoke_mode: String,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
382pub struct ProvisionedConcurrencyConfig {
383 pub requested: i64,
384 pub allocated: i64,
385 pub status: String,
386 pub last_modified: DateTime<Utc>,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
390pub struct CodeSigningConfig {
391 pub csc_id: String,
392 pub csc_arn: String,
393 pub description: String,
394 pub allowed_publishers: Vec<String>,
395 pub untrusted_artifact_action: String,
396 pub last_modified: DateTime<Utc>,
397}
398
399#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct EventInvokeConfig {
401 pub function_arn: String,
402 pub maximum_event_age: i64,
403 pub maximum_retry_attempts: i64,
404 #[serde(default)]
414 pub destination_config: Option<serde_json::Value>,
415 pub last_modified: DateTime<Utc>,
416}
417
418#[derive(Debug, Clone, Serialize, Deserialize)]
419pub struct RuntimeManagementConfig {
420 pub update_runtime_on: String,
421 pub runtime_version_arn: String,
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize, Default)]
425pub struct FunctionScalingConfig {
426 pub min_execution_environments: Option<i64>,
431 pub max_execution_environments: Option<i64>,
434}
435
436#[derive(Debug, Clone, Serialize, Deserialize, Default)]
437pub struct AccountSettings {
438 pub concurrent_executions: i64,
439 pub code_size_zipped: i64,
440 pub code_size_unzipped: i64,
441 pub total_code_size: i64,
442}
443
444impl LambdaState {
445 pub fn new(account_id: &str, region: &str) -> Self {
446 Self {
447 account_id: account_id.to_string(),
448 region: region.to_string(),
449 functions: BTreeMap::new(),
450 event_source_mappings: BTreeMap::new(),
451 invocations: Vec::new(),
452 aliases: BTreeMap::new(),
453 function_versions: BTreeMap::new(),
454 function_version_snapshots: BTreeMap::new(),
455 layers: BTreeMap::new(),
456 function_url_configs: BTreeMap::new(),
457 function_concurrency: BTreeMap::new(),
458 provisioned_concurrency: BTreeMap::new(),
459 code_signing_configs: BTreeMap::new(),
460 function_code_signing: BTreeMap::new(),
461 event_invoke_configs: BTreeMap::new(),
462 runtime_management: BTreeMap::new(),
463 scaling_configs: BTreeMap::new(),
464 recursion_configs: BTreeMap::new(),
465 account_settings: None,
466 capacity_providers: BTreeMap::new(),
467 durable_executions: BTreeMap::new(),
468 durable_execution_callbacks: BTreeMap::new(),
469 }
470 }
471
472 pub fn reset(&mut self) {
473 self.functions.clear();
474 self.event_source_mappings.clear();
475 self.invocations.clear();
476 self.aliases.clear();
477 self.function_versions.clear();
478 self.function_version_snapshots.clear();
479 self.layers.clear();
480 self.function_url_configs.clear();
481 self.function_concurrency.clear();
482 self.provisioned_concurrency.clear();
483 self.code_signing_configs.clear();
484 self.function_code_signing.clear();
485 self.event_invoke_configs.clear();
486 self.runtime_management.clear();
487 self.scaling_configs.clear();
488 self.recursion_configs.clear();
489 self.account_settings = None;
490 self.capacity_providers.clear();
491 self.durable_executions.clear();
492 self.durable_execution_callbacks.clear();
493 }
494}
495
496pub type SharedLambdaState =
497 Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<LambdaState>>>;
498
499impl fakecloud_core::multi_account::AccountState for LambdaState {
500 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
501 Self::new(account_id, region)
502 }
503}
504
505pub const LAMBDA_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
506
507#[derive(Debug, Serialize, Deserialize)]
508pub struct LambdaSnapshot {
509 pub schema_version: u32,
510 #[serde(default)]
511 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<LambdaState>>,
512 #[serde(default)]
513 pub state: Option<LambdaState>,
514}
515
516#[cfg(test)]
517mod tests {
518 use super::*;
519
520 #[test]
521 fn new_has_empty_collections() {
522 let state = LambdaState::new("123456789012", "us-east-1");
523 assert_eq!(state.account_id, "123456789012");
524 assert_eq!(state.region, "us-east-1");
525 assert!(state.functions.is_empty());
526 assert!(state.event_source_mappings.is_empty());
527 assert!(state.invocations.is_empty());
528 }
529
530 #[test]
531 fn reset_clears_collections() {
532 let mut state = LambdaState::new("123456789012", "us-east-1");
533 state.invocations.push(LambdaInvocation {
534 function_arn: "arn".to_string(),
535 payload: "p".to_string(),
536 timestamp: Utc::now(),
537 source: "s".to_string(),
538 });
539 state.reset();
540 assert!(state.invocations.is_empty());
541 }
542}