Skip to main content

fakecloud_cloudfront/
state.rs

1//! In-memory state for CloudFront resources.
2
3use std::collections::BTreeMap;
4use std::sync::Arc;
5
6use chrono::{DateTime, Utc};
7use parking_lot::RwLock;
8use serde::{Deserialize, Serialize};
9
10use crate::cfunctions::StoredConnectionFunction;
11use crate::extras::{StoredAnycastIpList, StoredResourcePolicy, StoredTrustStore, StoredVpcOrigin};
12use crate::extras2::StoredConnectionGroup;
13use crate::fle::{
14    StoredFieldLevelEncryption, StoredFieldLevelEncryptionProfile, StoredRealtimeLogConfig,
15};
16use crate::functions::{
17    StoredFunction, StoredKeyGroup, StoredKeyValueStore, StoredMonitoringSubscription,
18    StoredOriginAccessIdentity, StoredPublicKey,
19};
20use crate::model::{DistributionConfig, InvalidationBatch};
21use crate::policies::{
22    StoredCachePolicy, StoredContinuousDeploymentPolicy, StoredOriginAccessControl,
23    StoredOriginRequestPolicy, StoredResponseHeadersPolicy,
24};
25use crate::streaming::StoredStreamingDistribution;
26use crate::tenants::{StoredDistributionTenant, StoredTenantInvalidation};
27
28pub type SharedCloudFrontState = Arc<RwLock<CloudFrontAccounts>>;
29
30#[derive(Debug, Default, Clone, Serialize, Deserialize)]
31pub struct CloudFrontAccounts {
32    pub accounts: BTreeMap<String, AccountState>,
33}
34
35/// On-disk snapshot envelope for CloudFront state. Versioned so format changes
36/// fail loudly on upgrade rather than silently mis-parsing.
37#[derive(Clone, Serialize, Deserialize)]
38pub struct CloudFrontSnapshot {
39    pub schema_version: u32,
40    #[serde(default)]
41    pub accounts: Option<CloudFrontAccounts>,
42}
43
44pub const CLOUDFRONT_SNAPSHOT_SCHEMA_VERSION: u32 = 1;
45
46impl CloudFrontAccounts {
47    pub fn new() -> Self {
48        Self::default()
49    }
50
51    pub fn account_count(&self) -> usize {
52        self.accounts.len()
53    }
54
55    pub fn entry(&mut self, account_id: &str) -> &mut AccountState {
56        self.accounts.entry(account_id.to_string()).or_default()
57    }
58
59    pub fn get(&self, account_id: &str) -> Option<&AccountState> {
60        self.accounts.get(account_id)
61    }
62}
63
64#[derive(Debug, Default, Clone, Serialize, Deserialize)]
65pub struct AccountState {
66    pub distributions: BTreeMap<String, StoredDistribution>,
67    pub invalidations: BTreeMap<String, StoredInvalidation>,
68    /// Tags keyed by ARN.
69    pub tags: BTreeMap<String, Vec<Tag>>,
70    pub origin_access_controls: BTreeMap<String, StoredOriginAccessControl>,
71    pub cache_policies: BTreeMap<String, StoredCachePolicy>,
72    pub origin_request_policies: BTreeMap<String, StoredOriginRequestPolicy>,
73    pub response_headers_policies: BTreeMap<String, StoredResponseHeadersPolicy>,
74    pub continuous_deployment_policies: BTreeMap<String, StoredContinuousDeploymentPolicy>,
75    pub functions: BTreeMap<String, StoredFunction>,
76    pub public_keys: BTreeMap<String, StoredPublicKey>,
77    pub key_groups: BTreeMap<String, StoredKeyGroup>,
78    pub key_value_stores: BTreeMap<String, StoredKeyValueStore>,
79    pub origin_access_identities: BTreeMap<String, StoredOriginAccessIdentity>,
80    /// Per-distribution monitoring subscription, keyed by distribution id.
81    pub monitoring_subscriptions: BTreeMap<String, StoredMonitoringSubscription>,
82    pub streaming_distributions: BTreeMap<String, StoredStreamingDistribution>,
83    pub field_level_encryptions: BTreeMap<String, StoredFieldLevelEncryption>,
84    pub field_level_encryption_profiles: BTreeMap<String, StoredFieldLevelEncryptionProfile>,
85    /// Realtime log configs keyed by ARN.
86    pub realtime_log_configs: BTreeMap<String, StoredRealtimeLogConfig>,
87    pub vpc_origins: BTreeMap<String, StoredVpcOrigin>,
88    pub anycast_ip_lists: BTreeMap<String, StoredAnycastIpList>,
89    pub trust_stores: BTreeMap<String, StoredTrustStore>,
90    /// Resource policies keyed by resource ARN.
91    pub resource_policies: BTreeMap<String, StoredResourcePolicy>,
92    pub connection_groups: BTreeMap<String, StoredConnectionGroup>,
93    pub distribution_tenants: BTreeMap<String, StoredDistributionTenant>,
94    pub tenant_invalidations: BTreeMap<String, StoredTenantInvalidation>,
95    pub connection_functions: BTreeMap<String, StoredConnectionFunction>,
96}
97
98impl CloudFrontAccounts {
99    /// Pre-seed the AWS-managed Cache, Origin Request, and Response
100    /// Headers policies into the default account so callers that look
101    /// them up by their well-known IDs (Terraform, CDK) get the same
102    /// shape they get against AWS. The IDs and names mirror the AWS
103    /// console output verbatim — the easiest way to keep tests source
104    /// of truth.
105    pub fn seed_managed_policies(&mut self, account_id: &str) {
106        let account = self.entry(account_id);
107        crate::policies::seed_managed(account);
108    }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct StoredDistribution {
113    pub id: String,
114    pub arn: String,
115    pub status: String,
116    pub last_modified_time: DateTime<Utc>,
117    pub domain_name: String,
118    pub in_progress_invalidation_batches: u32,
119    pub etag: String,
120    pub config: DistributionConfig,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct StoredInvalidation {
125    pub id: String,
126    pub distribution_id: String,
127    pub status: String,
128    pub create_time: DateTime<Utc>,
129    pub batch: InvalidationBatch,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
133pub struct Tag {
134    pub key: String,
135    pub value: Option<String>,
136}