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)]
112 pub last_update_status_reason: Option<String>,
113 #[serde(default)]
116 pub last_update_status_reason_code: Option<String>,
117}
118
119fn default_revision_id() -> String {
120 uuid::Uuid::new_v4().to_string()
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct AttachedLayer {
125 pub arn: String,
126 #[serde(default)]
127 pub code_size: i64,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct EventSourceMapping {
132 pub uuid: String,
133 pub function_arn: String,
134 pub event_source_arn: String,
135 pub batch_size: i64,
136 pub enabled: bool,
137 pub state: String,
138 pub last_modified: DateTime<Utc>,
139 #[serde(default)]
144 pub filter_patterns: Vec<String>,
145 #[serde(default)]
148 pub maximum_batching_window_in_seconds: Option<i64>,
149 #[serde(default)]
152 pub starting_position: Option<String>,
153 #[serde(default)]
156 pub starting_position_timestamp: Option<f64>,
157 #[serde(default)]
159 pub parallelization_factor: Option<i64>,
160 #[serde(default)]
163 pub function_response_types: Vec<String>,
164 #[serde(default)]
168 pub kms_key_arn: Option<String>,
169 #[serde(default)]
173 pub metrics_config: Option<serde_json::Value>,
174 #[serde(default)]
177 pub destination_config: Option<serde_json::Value>,
178 #[serde(default)]
181 pub maximum_retry_attempts: Option<i64>,
182 #[serde(default)]
184 pub maximum_record_age_in_seconds: Option<i64>,
185 #[serde(default)]
188 pub bisect_batch_on_function_error: Option<bool>,
189 #[serde(default)]
191 pub tumbling_window_in_seconds: Option<i64>,
192 #[serde(default)]
194 pub topics: Vec<String>,
195 #[serde(default)]
197 pub queues: Vec<String>,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct LambdaInvocation {
203 pub function_arn: String,
204 pub payload: String,
205 pub timestamp: DateTime<Utc>,
206 pub source: String,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct LambdaState {
211 pub account_id: String,
212 pub region: String,
213 #[serde(default)]
214 pub functions: BTreeMap<String, LambdaFunction>,
215 #[serde(default)]
216 pub event_source_mappings: BTreeMap<String, EventSourceMapping>,
217 #[serde(default, skip)]
219 pub invocations: Vec<LambdaInvocation>,
220 #[serde(default)]
222 pub aliases: BTreeMap<String, FunctionAlias>,
223 #[serde(default)]
225 pub function_versions: BTreeMap<String, Vec<String>>,
226 #[serde(default)]
230 pub function_version_snapshots: BTreeMap<String, BTreeMap<String, LambdaFunction>>,
231 #[serde(default)]
233 pub layers: BTreeMap<String, Layer>,
234 #[serde(default)]
236 pub function_url_configs: BTreeMap<String, FunctionUrlConfig>,
237 #[serde(default)]
239 pub function_concurrency: BTreeMap<String, i64>,
240 #[serde(default)]
242 pub provisioned_concurrency: BTreeMap<String, ProvisionedConcurrencyConfig>,
243 #[serde(default)]
245 pub code_signing_configs: BTreeMap<String, CodeSigningConfig>,
246 #[serde(default)]
248 pub function_code_signing: BTreeMap<String, String>,
249 #[serde(default)]
251 pub event_invoke_configs: BTreeMap<String, EventInvokeConfig>,
252 #[serde(default)]
254 pub runtime_management: BTreeMap<String, RuntimeManagementConfig>,
255 #[serde(default)]
257 pub scaling_configs: BTreeMap<String, FunctionScalingConfig>,
258 #[serde(default)]
260 pub recursion_configs: BTreeMap<String, String>,
261 #[serde(default)]
263 pub account_settings: Option<AccountSettings>,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct FunctionAlias {
268 pub alias_arn: String,
269 pub name: String,
270 pub function_version: String,
271 pub description: String,
272 pub revision_id: String,
273 pub routing_config: Option<serde_json::Value>,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct Layer {
278 pub layer_name: String,
279 pub layer_arn: String,
280 pub versions: Vec<LayerVersion>,
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct LayerVersion {
285 pub version: i64,
286 pub layer_version_arn: String,
287 pub description: String,
288 pub created_date: DateTime<Utc>,
289 pub compatible_runtimes: Vec<String>,
290 pub license_info: String,
291 pub policy: Option<String>,
292 #[serde(default)]
295 pub code_zip: Option<Vec<u8>>,
296 #[serde(default)]
297 pub code_sha256: String,
298 #[serde(default)]
299 pub code_size: i64,
300 #[serde(default)]
304 pub compatible_architectures: Vec<String>,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct FunctionUrlConfig {
309 pub function_arn: String,
310 pub function_url: String,
311 pub auth_type: String,
312 pub cors: Option<serde_json::Value>,
313 pub creation_time: DateTime<Utc>,
314 pub last_modified_time: DateTime<Utc>,
315 pub invoke_mode: String,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ProvisionedConcurrencyConfig {
320 pub requested: i64,
321 pub allocated: i64,
322 pub status: String,
323 pub last_modified: DateTime<Utc>,
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct CodeSigningConfig {
328 pub csc_id: String,
329 pub csc_arn: String,
330 pub description: String,
331 pub allowed_publishers: Vec<String>,
332 pub untrusted_artifact_action: String,
333 pub last_modified: DateTime<Utc>,
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct EventInvokeConfig {
338 pub function_arn: String,
339 pub maximum_event_age: i64,
340 pub maximum_retry_attempts: i64,
341 pub destination_config: serde_json::Value,
342 pub last_modified: DateTime<Utc>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct RuntimeManagementConfig {
347 pub update_runtime_on: String,
348 pub runtime_version_arn: String,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct FunctionScalingConfig {
353 pub maximum_concurrency: i64,
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize, Default)]
357pub struct AccountSettings {
358 pub concurrent_executions: i64,
359 pub code_size_zipped: i64,
360 pub code_size_unzipped: i64,
361 pub total_code_size: i64,
362}
363
364impl LambdaState {
365 pub fn new(account_id: &str, region: &str) -> Self {
366 Self {
367 account_id: account_id.to_string(),
368 region: region.to_string(),
369 functions: BTreeMap::new(),
370 event_source_mappings: BTreeMap::new(),
371 invocations: Vec::new(),
372 aliases: BTreeMap::new(),
373 function_versions: BTreeMap::new(),
374 function_version_snapshots: BTreeMap::new(),
375 layers: BTreeMap::new(),
376 function_url_configs: BTreeMap::new(),
377 function_concurrency: BTreeMap::new(),
378 provisioned_concurrency: BTreeMap::new(),
379 code_signing_configs: BTreeMap::new(),
380 function_code_signing: BTreeMap::new(),
381 event_invoke_configs: BTreeMap::new(),
382 runtime_management: BTreeMap::new(),
383 scaling_configs: BTreeMap::new(),
384 recursion_configs: BTreeMap::new(),
385 account_settings: None,
386 }
387 }
388
389 pub fn reset(&mut self) {
390 self.functions.clear();
391 self.event_source_mappings.clear();
392 self.invocations.clear();
393 self.aliases.clear();
394 self.function_versions.clear();
395 self.function_version_snapshots.clear();
396 self.layers.clear();
397 self.function_url_configs.clear();
398 self.function_concurrency.clear();
399 self.provisioned_concurrency.clear();
400 self.code_signing_configs.clear();
401 self.function_code_signing.clear();
402 self.event_invoke_configs.clear();
403 self.runtime_management.clear();
404 self.scaling_configs.clear();
405 self.recursion_configs.clear();
406 self.account_settings = None;
407 }
408}
409
410pub type SharedLambdaState =
411 Arc<RwLock<fakecloud_core::multi_account::MultiAccountState<LambdaState>>>;
412
413impl fakecloud_core::multi_account::AccountState for LambdaState {
414 fn new_for_account(account_id: &str, region: &str, _endpoint: &str) -> Self {
415 Self::new(account_id, region)
416 }
417}
418
419pub const LAMBDA_SNAPSHOT_SCHEMA_VERSION: u32 = 2;
420
421#[derive(Debug, Serialize, Deserialize)]
422pub struct LambdaSnapshot {
423 pub schema_version: u32,
424 #[serde(default)]
425 pub accounts: Option<fakecloud_core::multi_account::MultiAccountState<LambdaState>>,
426 #[serde(default)]
427 pub state: Option<LambdaState>,
428}
429
430#[cfg(test)]
431mod tests {
432 use super::*;
433
434 #[test]
435 fn new_has_empty_collections() {
436 let state = LambdaState::new("123456789012", "us-east-1");
437 assert_eq!(state.account_id, "123456789012");
438 assert_eq!(state.region, "us-east-1");
439 assert!(state.functions.is_empty());
440 assert!(state.event_source_mappings.is_empty());
441 assert!(state.invocations.is_empty());
442 }
443
444 #[test]
445 fn reset_clears_collections() {
446 let mut state = LambdaState::new("123456789012", "us-east-1");
447 state.invocations.push(LambdaInvocation {
448 function_arn: "arn".to_string(),
449 payload: "p".to_string(),
450 timestamp: Utc::now(),
451 source: "s".to_string(),
452 });
453 state.reset();
454 assert!(state.invocations.is_empty());
455 }
456}