init bucketmeta

This commit is contained in:
weisd
2024-09-27 16:33:56 +08:00
parent 96644d3430
commit 3edcac4d3c
22 changed files with 687 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
use serde::{Deserialize, Serialize};
use super::name::Name;
// 定义common结构体
#[derive(Serialize, Deserialize, Debug)]
struct Common {
pub id: String,
pub filter: S3Key,
pub events: Vec<Name>,
}
// 定义Queue结构体
#[derive(Serialize, Deserialize, Debug)]
struct Queue {
pub common: Common,
pub arn: ARN,
}
// 定义ARN结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct ARN {
pub target_id: TargetID,
pub region: String,
}
// 定义TargetID结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct TargetID {
pub id: String,
pub name: String,
}
// 定义FilterRule结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct FilterRule {
pub name: String,
pub value: String,
}
// 定义FilterRuleList结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct FilterRuleList {
pub rules: Vec<FilterRule>,
}
// 定义S3Key结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct S3Key {
pub rule_list: FilterRuleList,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Lambda {
arn: String,
}
// 定义Topic结构体
#[derive(Serialize, Deserialize, Debug)]
pub struct Topic {
arn: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
queue_list: Vec<Queue>,
lambda_list: Vec<Lambda>,
topic_list: Vec<Topic>,
}

View File

@@ -0,0 +1,2 @@
pub(crate) mod config;
mod name;

View File

@@ -0,0 +1,98 @@
use std::fmt::Display;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Name {
ObjectAccessedGet = 1,
ObjectAccessedGetRetention,
ObjectAccessedGetLegalHold,
ObjectAccessedHead,
ObjectAccessedAttributes,
ObjectCreatedCompleteMultipartUpload,
ObjectCreatedCopy,
ObjectCreatedPost,
ObjectCreatedPut,
ObjectCreatedPutRetention,
ObjectCreatedPutLegalHold,
ObjectCreatedPutTagging,
ObjectCreatedDeleteTagging,
ObjectRemovedDelete,
ObjectRemovedDeleteMarkerCreated,
ObjectRemovedDeleteAllVersions,
ObjectRemovedNoOP,
BucketCreated,
BucketRemoved,
ObjectReplicationFailed,
ObjectReplicationComplete,
ObjectReplicationMissedThreshold,
ObjectReplicationReplicatedAfterThreshold,
ObjectReplicationNotTracked,
ObjectRestorePost,
ObjectRestoreCompleted,
ObjectTransitionFailed,
ObjectTransitionComplete,
ObjectManyVersions,
ObjectLargeVersions,
PrefixManyFolders,
ILMDelMarkerExpirationDelete,
ObjectAccessedAll,
ObjectCreatedAll,
ObjectRemovedAll,
ObjectReplicationAll,
ObjectRestoreAll,
ObjectTransitionAll,
ObjectScannerAll,
Everything,
}
impl Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
Name::ObjectAccessedGet => "s3:ObjectAccessed:Get",
Name::ObjectAccessedGetRetention => "s3:ObjectAccessed:GetRetention",
Name::ObjectAccessedGetLegalHold => "s3:ObjectAccessed:GetLegalHold",
Name::ObjectAccessedHead => "s3:ObjectAccessed:Head",
Name::ObjectAccessedAttributes => "s3:ObjectAccessed:Attributes",
Name::ObjectCreatedCompleteMultipartUpload => "s3:ObjectCreated:CompleteMultipartUpload",
Name::ObjectCreatedCopy => "s3:ObjectCreated:Copy",
Name::ObjectCreatedPost => "s3:ObjectCreated:Post",
Name::ObjectCreatedPut => "s3:ObjectCreated:Put",
Name::ObjectCreatedPutRetention => "s3:ObjectCreated:PutRetention",
Name::ObjectCreatedPutLegalHold => "s3:ObjectCreated:PutLegalHold",
Name::ObjectCreatedPutTagging => "s3:ObjectCreated:PutTagging",
Name::ObjectCreatedDeleteTagging => "s3:ObjectCreated:DeleteTagging",
Name::ObjectRemovedDelete => "s3:ObjectRemoved:Delete",
Name::ObjectRemovedDeleteMarkerCreated => "s3:ObjectRemoved:DeleteMarkerCreated",
Name::ObjectRemovedDeleteAllVersions => "s3:ObjectRemoved:DeleteAllVersions",
Name::ObjectRemovedNoOP => "s3:ObjectRemoved:NoOP",
Name::BucketCreated => "s3:BucketCreated:*",
Name::BucketRemoved => "s3:BucketRemoved:*",
Name::ObjectReplicationFailed => "s3:Replication:OperationFailedReplication",
Name::ObjectReplicationComplete => "s3:Replication:OperationCompletedReplication",
Name::ObjectReplicationMissedThreshold => "s3:Replication:OperationMissedThreshold",
Name::ObjectReplicationReplicatedAfterThreshold => "s3:Replication:OperationReplicatedAfterThreshold",
Name::ObjectReplicationNotTracked => "s3:Replication:OperationNotTracked",
Name::ObjectRestorePost => "s3:ObjectRestore:Post",
Name::ObjectRestoreCompleted => "s3:ObjectRestore:Completed",
Name::ObjectTransitionFailed => "s3:ObjectTransition:Failed",
Name::ObjectTransitionComplete => "s3:ObjectTransition:Complete",
Name::ObjectManyVersions => "s3:Scanner:ManyVersions",
Name::ObjectLargeVersions => "s3:Scanner:LargeVersions",
Name::PrefixManyFolders => "s3:Scanner:BigPrefix",
Name::ILMDelMarkerExpirationDelete => "s3:LifecycleDelMarkerExpiration:Delete",
Name::ObjectAccessedAll => "s3:ObjectAccessed:*",
Name::ObjectCreatedAll => "s3:ObjectCreated:*",
Name::ObjectRemovedAll => "s3:ObjectRemoved:*",
Name::ObjectReplicationAll => "s3:Replication:*",
Name::ObjectRestoreAll => "s3:ObjectRestore:*",
Name::ObjectTransitionAll => "s3:ObjectTransition:*",
Name::ObjectScannerAll => "s3:Scanner:*",
Name::Everything => "*",
}
)
}
}

View File

@@ -0,0 +1,8 @@
use super::{prefix::Prefix, tag::Tag};
pub struct And {
pub object_size_greater_than: i64,
pub object_size_less_than: i64,
pub prefix: Prefix,
pub tags: Vec<Tag>,
}

View File

@@ -0,0 +1,27 @@
use time::OffsetDateTime;
// ExpirationDays is a type alias to unmarshal Days in Expiration
pub type ExpirationDays = usize;
#[derive(Debug, Clone, PartialEq)]
pub struct ExpirationDate(OffsetDateTime);
#[derive(Debug)]
pub struct ExpireDeleteMarker {
pub marker: Boolean,
}
#[derive(Debug)]
pub struct Boolean {
pub val: bool,
pub set: bool,
}
#[derive(Debug)]
pub struct Expiration {
pub days: Option<ExpirationDays>,
pub date: Option<ExpirationDate>,
pub delete_marker: ExpireDeleteMarker,
pub delete_all: Boolean,
pub set: bool,
}

View File

@@ -0,0 +1,19 @@
use super::{and::And, prefix::Prefix, tag::Tag};
pub struct Filter {
pub set: bool,
pub prefix: Prefix,
pub object_size_greater_than: Option<i64>,
pub object_size_less_than: Option<i64>,
pub and_condition: And,
pub and_set: bool,
pub tag: Tag,
pub tag_set: bool,
// 使用HashMap存储缓存的标签
pub cached_tags: std::collections::HashMap<String, String>,
}

View File

@@ -0,0 +1,5 @@
mod and;
mod expiration;
mod fileter;
mod prefix;
mod tag;

View File

@@ -0,0 +1,4 @@
pub struct Prefix {
pub val: String,
pub set: bool,
}

View File

@@ -0,0 +1,5 @@
#[derive(Debug)]
pub struct Tag {
pub key: String,
pub value: String,
}

View File

@@ -0,0 +1,68 @@
use time::OffsetDateTime;
use super::{event, policy::bucket_policy::BucketPolicy};
#[derive(Debug, Default)]
pub struct BucketMetadata {
format: u16,
version: u16,
pub name: String,
pub created: Option<OffsetDateTime>,
pub lock_enabled: bool, // 虽然标记为不使用,但可能需要保留
pub policy_config_json: Vec<u8>,
pub notification_config_xml: Vec<u8>,
pub lifecycle_config_xml: Vec<u8>,
pub object_lock_config_xml: Vec<u8>,
pub versioning_config_xml: Vec<u8>,
pub encryption_config_xml: Vec<u8>,
pub tagging_config_xml: Vec<u8>,
pub quota_config_json: Vec<u8>,
pub replication_config_xml: Vec<u8>,
pub bucket_targets_config_json: Vec<u8>,
pub bucket_targets_config_meta_json: Vec<u8>,
pub policy_config_updated_at: Option<OffsetDateTime>,
pub object_lock_config_updated_at: Option<OffsetDateTime>,
pub encryption_config_updated_at: Option<OffsetDateTime>,
pub tagging_config_updated_at: Option<OffsetDateTime>,
pub quota_config_updated_at: Option<OffsetDateTime>,
pub replication_config_updated_at: Option<OffsetDateTime>,
pub versioning_config_updated_at: Option<OffsetDateTime>,
pub lifecycle_config_updated_at: Option<OffsetDateTime>,
pub notification_config_updated_at: Option<OffsetDateTime>,
pub bucket_targets_config_updated_at: Option<OffsetDateTime>,
pub bucket_targets_config_meta_updated_at: Option<OffsetDateTime>,
// 新增UpdatedAt字段
new_field_updated_at: Option<OffsetDateTime>,
// 私有字段,需要原子更新
policy_config: Option<BucketPolicy>, // 假设Policy是一个已经定义好的结构体
notification_config: Option<event::config::Config>,
lifecycle_config: Option<Lifecycle>,
object_lock_config: Option<ObjectLock>,
versioning_config: Option<Versioning>,
sse_config: Option<BucketSSEConfig>,
tagging_config: Option<Tags>,
quota_config: Option<BucketQuota>,
replication_config: Option<ReplicationConfig>,
bucket_target_config: Option<BucketTargets>,
bucket_target_config_meta: Option<std::collections::HashMap<String, String>>,
}
#[derive(Debug, Default)]
struct Lifecycle;
#[derive(Debug, Default)]
struct ObjectLock;
#[derive(Debug, Default)]
struct Versioning;
#[derive(Debug, Default)]
struct BucketSSEConfig;
#[derive(Debug, Default)]
struct Tags;
#[derive(Debug, Default)]
struct BucketQuota;
#[derive(Debug, Default)]
struct ReplicationConfig;
#[derive(Debug, Default)]
struct BucketTargets;

View File

@@ -0,0 +1,4 @@
mod event;
mod lifecycle;
mod metadata;
mod policy;

View File

@@ -0,0 +1,141 @@
use std::{collections::HashSet, default};
#[derive(Debug, Default)]
pub struct ActionSet(HashSet<Action>);
impl ActionSet {}
// 定义Action枚举类型
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum Action {
AbortMultipartUpload,
CreateBucket,
DeleteBucket,
ForceDeleteBucket,
DeleteBucketPolicy,
DeleteBucketCors,
DeleteObject,
GetBucketLocation,
GetBucketNotification,
GetBucketPolicy,
GetBucketCors,
GetObject,
GetObjectAttributes,
HeadBucket,
ListAllMyBuckets,
ListBucket,
GetBucketPolicyStatus,
ListBucketVersions,
ListBucketMultipartUploads,
ListenNotification,
ListenBucketNotification,
ListMultipartUploadParts,
PutBucketLifecycle,
GetBucketLifecycle,
PutBucketNotification,
PutBucketPolicy,
PutBucketCors,
PutObject,
DeleteObjectVersion,
DeleteObjectVersionTagging,
GetObjectVersion,
GetObjectVersionAttributes,
GetObjectVersionTagging,
PutObjectVersionTagging,
BypassGovernanceRetention,
PutObjectRetention,
GetObjectRetention,
GetObjectLegalHold,
PutObjectLegalHold,
GetBucketObjectLockConfiguration,
PutBucketObjectLockConfiguration,
GetBucketTagging,
PutBucketTagging,
GetObjectTagging,
PutObjectTagging,
DeleteObjectTagging,
PutBucketEncryption,
GetBucketEncryption,
PutBucketVersioning,
GetBucketVersioning,
PutReplicationConfiguration,
GetReplicationConfiguration,
ReplicateObject,
ReplicateDelete,
ReplicateTags,
GetObjectVersionForReplication,
RestoreObject,
ResetBucketReplicationState,
PutObjectFanOut,
#[default]
AllActions,
}
impl Action {
// 将字符串转换为Action枚举
fn from_str(s: &str) -> Option<Self> {
match s {
"s3:AbortMultipartUpload" => Some(Action::AbortMultipartUpload),
"s3:CreateBucket" => Some(Action::CreateBucket),
"s3:DeleteBucket" => Some(Action::DeleteBucket),
"s3:ForceDeleteBucket" => Some(Action::ForceDeleteBucket),
"s3:DeleteBucketPolicy" => Some(Action::DeleteBucketPolicy),
"s3:DeleteBucketCors" => Some(Action::DeleteBucketCors),
"s3:DeleteObject" => Some(Action::DeleteObject),
"s3:GetBucketLocation" => Some(Action::GetBucketLocation),
"s3:GetBucketNotification" => Some(Action::GetBucketNotification),
"s3:GetBucketPolicy" => Some(Action::GetBucketPolicy),
"s3:GetBucketCors" => Some(Action::GetBucketCors),
"s3:GetObject" => Some(Action::GetObject),
"s3:GetObjectAttributes" => Some(Action::GetObjectAttributes),
"s3:HeadBucket" => Some(Action::HeadBucket),
"s3:ListAllMyBuckets" => Some(Action::ListAllMyBuckets),
"s3:ListBucket" => Some(Action::ListBucket),
"s3:GetBucketPolicyStatus" => Some(Action::GetBucketPolicyStatus),
"s3:ListBucketVersions" => Some(Action::ListBucketVersions),
"s3:ListBucketMultipartUploads" => Some(Action::ListBucketMultipartUploads),
"s3:ListenNotification" => Some(Action::ListenNotification),
"s3:ListenBucketNotification" => Some(Action::ListenBucketNotification),
"s3:ListMultipartUploadParts" => Some(Action::ListMultipartUploadParts),
"s3:PutLifecycleConfiguration" => Some(Action::PutBucketLifecycle),
"s3:GetLifecycleConfiguration" => Some(Action::GetBucketLifecycle),
"s3:PutBucketNotification" => Some(Action::PutBucketNotification),
"s3:PutBucketPolicy" => Some(Action::PutBucketPolicy),
"s3:PutBucketCors" => Some(Action::PutBucketCors),
"s3:PutObject" => Some(Action::PutObject),
"s3:DeleteObjectVersion" => Some(Action::DeleteObjectVersion),
"s3:DeleteObjectVersionTagging" => Some(Action::DeleteObjectVersionTagging),
"s3:GetObjectVersion" => Some(Action::GetObjectVersion),
"s3:GetObjectVersionAttributes" => Some(Action::GetObjectVersionAttributes),
"s3:GetObjectVersionTagging" => Some(Action::GetObjectVersionTagging),
"s3:PutObjectVersionTagging" => Some(Action::PutObjectVersionTagging),
"s3:BypassGovernanceRetention" => Some(Action::BypassGovernanceRetention),
"s3:PutObjectRetention" => Some(Action::PutObjectRetention),
"s3:GetObjectRetention" => Some(Action::GetObjectRetention),
"s3:GetObjectLegalHold" => Some(Action::GetObjectLegalHold),
"s3:PutObjectLegalHold" => Some(Action::PutObjectLegalHold),
"s3:GetBucketObjectLockConfiguration" => Some(Action::GetBucketObjectLockConfiguration),
"s3:PutBucketObjectLockConfiguration" => Some(Action::PutBucketObjectLockConfiguration),
"s3:GetBucketTagging" => Some(Action::GetBucketTagging),
"s3:PutBucketTagging" => Some(Action::PutBucketTagging),
"s3:GetObjectTagging" => Some(Action::GetObjectTagging),
"s3:PutObjectTagging" => Some(Action::PutObjectTagging),
"s3:DeleteObjectTagging" => Some(Action::DeleteObjectTagging),
"s3:PutEncryptionConfiguration" => Some(Action::PutBucketEncryption),
"s3:GetEncryptionConfiguration" => Some(Action::GetBucketEncryption),
"s3:PutBucketVersioning" => Some(Action::PutBucketVersioning),
"s3:GetBucketVersioning" => Some(Action::GetBucketVersioning),
"s3:PutReplicationConfiguration" => Some(Action::PutReplicationConfiguration),
"s3:GetReplicationConfiguration" => Some(Action::GetReplicationConfiguration),
"s3:ReplicateObject" => Some(Action::ReplicateObject),
"s3:ReplicateDelete" => Some(Action::ReplicateDelete),
"s3:ReplicateTags" => Some(Action::ReplicateTags),
"s3:GetObjectVersionForReplication" => Some(Action::GetObjectVersionForReplication),
"s3:RestoreObject" => Some(Action::RestoreObject),
"s3:ResetBucketReplicationState" => Some(Action::ResetBucketReplicationState),
"s3:PutObjectFanOut" => Some(Action::PutObjectFanOut),
"s3:*" => Some(Action::AllActions),
_ => None,
}
}
}

View File

@@ -0,0 +1,39 @@
use std::collections::HashMap;
use super::{
action::{Action, ActionSet},
condition::function::Functions,
effect::Effect,
principal::Principal,
resource::ResourceSet,
};
#[derive(Debug, Default)]
pub struct BucketPolicyArgs {
account_name: String,
groups: Vec<String>,
action: Action,
bucket_name: String,
condition_values: HashMap<String, Vec<String>>,
is_owner: bool,
object_name: String,
}
#[derive(Debug, Default)]
pub struct BPStatement {
sid: String,
effect: Effect,
principal: Principal,
actions: ActionSet,
not_actions: Option<ActionSet>,
resources: ResourceSet,
conditions: Option<Functions>,
}
#[derive(Debug, Default)]
pub struct BucketPolicy {
pub id: String,
pub version: String,
pub statements: Vec<BPStatement>,
}

View File

@@ -0,0 +1,68 @@
use std::{
collections::{HashMap, HashSet},
fmt::{Debug, Display},
};
use super::name::Name;
#[derive(Debug, Clone)]
pub struct Key {
name: String,
variable: String,
}
// 定义ValueSet类型
pub type ValueSet = HashSet<String>;
// 定义Function trait
pub trait Function {
// evaluate方法
fn evaluate(&self, values: &HashMap<Key, ValueSet>) -> bool;
// key方法
fn key(&self) -> Key;
// name方法
fn name(&self) -> Name;
// String方法
fn to_string(&self) -> String;
// to_map方法
fn to_map(&self) -> HashMap<Key, ValueSet>;
// clone方法
fn clone(&self) -> Box<dyn Function>;
}
impl Display for dyn Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.to_string())
}
}
impl Debug for dyn Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.to_string())
}
}
// 定义Functions类型
pub struct Functions(Vec<Box<dyn Function>>);
impl Display for Functions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[")?;
for v in self.0.iter() {
write!(f, "{:?}", v.to_string())?;
}
write!(f, "]")
}
}
impl Debug for Functions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Functions").field(&self.0).finish()
}
}

View File

@@ -0,0 +1,3 @@
pub mod function;
pub mod keyname;
pub mod name;

View File

@@ -0,0 +1,68 @@
// 定义Name枚举类型
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Name {
StringEquals,
StringNotEquals,
StringEqualsIgnoreCase,
StringNotEqualsIgnoreCase,
StringLike,
StringNotLike,
BinaryEquals,
IpAddress,
NotIpAddress,
Null,
Bool,
NumericEquals,
NumericNotEquals,
NumericLessThan,
NumericLessThanEquals,
NumericGreaterThan,
NumericGreaterThanIfExists,
NumericGreaterThanEquals,
DateEquals,
DateNotEquals,
DateLessThan,
DateLessThanEquals,
DateGreaterThan,
DateGreaterThanEquals,
ForAllValues,
ForAnyValue,
}
// 实现Display trait用于打印
impl std::fmt::Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
Name::StringEquals => "StringEquals",
Name::StringNotEquals => "StringNotEquals",
Name::StringEqualsIgnoreCase => "StringEqualsIgnoreCase",
Name::StringNotEqualsIgnoreCase => "StringNotEqualsIgnoreCase",
Name::StringLike => "StringLike",
Name::StringNotLike => "StringNotLike",
Name::BinaryEquals => "BinaryEquals",
Name::IpAddress => "IpAddress",
Name::NotIpAddress => "NotIpAddress",
Name::Null => "Null",
Name::Bool => "Bool",
Name::NumericEquals => "NumericEquals",
Name::NumericNotEquals => "NumericNotEquals",
Name::NumericLessThan => "NumericLessThan",
Name::NumericLessThanEquals => "NumericLessThanEquals",
Name::NumericGreaterThan => "NumericGreaterThan",
Name::NumericGreaterThanIfExists => "NumericGreaterThanIfExists",
Name::NumericGreaterThanEquals => "NumericGreaterThanEquals",
Name::DateEquals => "DateEquals",
Name::DateNotEquals => "DateNotEquals",
Name::DateLessThan => "DateLessThan",
Name::DateLessThanEquals => "DateLessThanEquals",
Name::DateGreaterThan => "DateGreaterThan",
Name::DateGreaterThanEquals => "DateGreaterThanEquals",
Name::ForAllValues => "ForAllValues",
Name::ForAnyValue => "ForAnyValue",
}
)
}
}

View File

@@ -0,0 +1,21 @@
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Effect {
#[default]
Allow,
Deny,
}
// 实现从字符串解析Effect的功能
impl FromStr for Effect {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Allow" => Ok(Effect::Allow),
"Deny" => Ok(Effect::Deny),
_ => Err(()),
}
}
}

View File

@@ -0,0 +1,6 @@
pub mod action;
pub mod bucket_policy;
pub mod condition;
pub mod effect;
pub mod principal;
pub mod resource;

View File

@@ -0,0 +1,6 @@
use std::collections::HashSet;
#[derive(Debug, Clone, Default)]
pub struct Principal {
aws: HashSet<String>,
}

View File

@@ -0,0 +1,24 @@
use std::{collections::HashSet, default};
// 定义ResourceARNType枚举类型
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ResourceARNType {
#[default]
UnknownARN,
ResourceARNS3,
ResourceARNKMS,
}
// 定义资源ARN前缀
const RESOURCE_ARN_PREFIX: &str = "arn:aws:s3:::";
const RESOURCE_ARN_KMS_PREFIX: &str = "arn:minio:kms::::";
// 定义Resource结构体
#[derive(Debug, Default)]
pub struct Resource {
pattern: String,
r#type: ResourceARNType,
}
#[derive(Debug, Default)]
pub struct ResourceSet(HashSet<Resource>);

View File

@@ -15,3 +15,5 @@ pub mod store;
pub mod store_api;
mod store_init;
mod utils;
mod bucket;