Source code for dxaws_s3.models
"""dxaws-s3 models.
Desired -> Current -> Plan(operations) -> Result
"""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Literal
[docs]
class BucketPurpose(str, Enum):
GENERAL = "general"
CLOUDFRONT_ORIGIN = "cloudfront_origin"
EncryptionMode = Literal["SSE-S3", "SSE-KMS", "NONE"]
[docs]
@dataclass(frozen=True)
class CloudFrontOriginDesired:
distribution_arn: str | None = None
distribution_arns: list[str] = field(default_factory=list)
oai_canonical_user_id: str | None = None # future
[docs]
@dataclass(frozen=True)
class S3BucketDesired:
name: str
region: str | None = None
purpose: BucketPurpose = BucketPurpose.GENERAL
tags: dict[str, str] = field(default_factory=dict)
block_public_access: bool = True
enforce_tls: bool = True
encryption: EncryptionMode = "SSE-S3"
kms_key_arn: str | None = None
versioning: bool = False
lifecycle_rules: list[dict[str, Any]] = field(default_factory=list)
cors_rules: list[dict[str, Any]] = field(default_factory=list)
cloudfront: CloudFrontOriginDesired | None = None
@property
def cloudfront_distribution_arns(self) -> list[str]:
cf = self.cloudfront
if cf is None:
return []
arns: list[str] = []
if cf.distribution_arn:
arns.append(cf.distribution_arn)
for a in (cf.distribution_arns or []):
if a and a not in arns:
arns.append(a)
return arns
[docs]
@dataclass(frozen=True)
class S3BucketCurrent:
exists: bool
name: str
arn: str | None = None
regional_domain_name: str | None = None
tags: dict[str, str] = field(default_factory=dict)
block_public_access: bool | None = None
encryption: EncryptionMode | None = None
kms_key_arn: str | None = None
versioning: bool | None = None
bucket_policy_json: str | None = None
[docs]
class ActionType(str, Enum):
CREATE_BUCKET = "create_bucket"
PUT_TAGS = "put_tags"
PUT_PUBLIC_ACCESS_BLOCK = "put_public_access_block"
PUT_ENCRYPTION = "put_encryption"
PUT_VERSIONING = "put_versioning"
PUT_BUCKET_POLICY = "put_bucket_policy"
# Standardized operation verbs for canonical plan structure
[docs]
class OperationType(str, Enum):
create = "create"
update = "update"
delete = "delete"
noop = "noop"
# Canonical S3 bucket operation structure
[docs]
@dataclass(frozen=True)
class S3BucketOperation:
op_type: OperationType
type: ActionType
target: str
reason: str
payload: dict[str, Any] = field(default_factory=dict)
[docs]
@staticmethod
def for_bucket(
*,
op_type: OperationType,
type: ActionType,
bucket_name: str,
reason: str,
payload: dict[str, Any] | None = None,
) -> "S3BucketOperation":
return S3BucketOperation(
op_type=op_type,
type=type,
target=f"s3:bucket:{bucket_name}",
reason=reason,
payload=payload or {},
)
[docs]
@dataclass(frozen=True)
class S3BucketPlan:
desired: S3BucketDesired
current: S3BucketCurrent
operations: list[S3BucketOperation]
metadata: dict[str, Any] = field(default_factory=dict)
@property
def is_noop(self) -> bool:
return len(self.operations) == 0
[docs]
@dataclass(frozen=True)
class S3BucketResult:
name: str
arn: str
regional_domain_name: str