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