use crate::{ArnError, Resource, ARN, WILD};
#[derive(Debug)]
pub struct ResourceBuilder {
resource: Resource,
}
#[derive(Debug)]
pub struct ArnBuilder {
arn: ARN,
}
impl ResourceBuilder {
pub fn new(id_or_path: &str) -> Self {
if id_or_path.contains(':') {
panic!("You can't create qualified things");
} else if id_or_path.contains('/') {
ResourceBuilder {
resource: Resource::Path(id_or_path.to_string()),
}
} else {
ResourceBuilder {
resource: Resource::Id(id_or_path.to_string()),
}
}
}
pub fn any() -> Self {
Self::new(WILD)
}
#[allow(clippy::wrong_self_convention)]
pub fn is_a(&mut self, the_type: &str) -> &mut Self {
let new_type = the_type.to_string();
match &self.resource {
Resource::Any => {
self.resource = Resource::TypedId {
id: WILD.to_string(),
the_type: new_type,
}
}
Resource::Id(id) => {
self.resource = Resource::TypedId {
id: id.clone(),
the_type: new_type,
}
}
Resource::Path(path) => {
self.resource = Resource::TypedId {
id: path.clone(),
the_type: new_type,
}
}
Resource::TypedId { the_type: _, id } => {
self.resource = Resource::TypedId {
id: id.clone(),
the_type: new_type,
}
}
Resource::QTypedId {
the_type: _,
id,
qualifier,
} => {
self.resource = Resource::QTypedId {
id: id.clone(),
the_type: new_type,
qualifier: qualifier.clone(),
}
}
};
self
}
#[allow(clippy::wrong_self_convention)]
pub fn is_an(&mut self, the_type: &str) -> &mut Self {
self.is_a(the_type)
}
pub fn has_type(&mut self, the_type: &str) -> &mut Self {
self.is_a(the_type)
}
pub fn with(&mut self, qualifier: &str) -> &mut Self {
let new_qualifier = qualifier.to_string();
match &self.resource {
Resource::Any => {
self.resource = Resource::QTypedId {
id: WILD.to_string(),
the_type: WILD.to_string(),
qualifier: new_qualifier,
}
}
Resource::Id(id) => {
self.resource = Resource::QTypedId {
id: id.clone(),
the_type: WILD.to_string(),
qualifier: new_qualifier,
}
}
Resource::Path(path) => {
self.resource = Resource::QTypedId {
id: path.clone(),
the_type: WILD.to_string(),
qualifier: new_qualifier,
}
}
Resource::TypedId { the_type, id } => {
self.resource = Resource::QTypedId {
id: id.clone(),
the_type: the_type.to_string(),
qualifier: new_qualifier,
}
}
Resource::QTypedId {
the_type,
id,
qualifier: _,
} => {
self.resource = Resource::QTypedId {
id: id.clone(),
the_type: the_type.to_string(),
qualifier: new_qualifier,
}
}
};
self
}
pub fn with_version(&mut self, version: i32) -> &mut Self {
self.with(version.to_string().as_str());
self
}
pub fn build(&self) -> Result<Resource, ArnError> {
let new_resource = self.resource.clone();
new_resource.validate().map(|_| new_resource)
}
}
impl ArnBuilder {
pub fn new(service: &str) -> Self {
ArnBuilder {
arn: ARN {
partition: None,
service: service.to_string(),
region: None,
account_id: None,
resource: Resource::Id(String::new()),
},
}
}
pub fn in_partition(&mut self, partition: &str) -> &mut Self {
self.arn.partition = Some(partition.to_string());
self
}
pub fn in_any_partition(&mut self) -> &mut Self {
self.arn.partition = None;
self
}
pub fn in_region(&mut self, region: &str) -> &mut Self {
self.arn.region = Some(region.to_string());
self
}
pub fn and_region(&mut self, region: &str) -> &mut Self {
self.in_region(region)
}
pub fn in_any_region(&mut self) -> &mut Self {
self.in_region(WILD)
}
pub fn in_account(&mut self, account: &str) -> &mut Self {
self.arn.account_id = Some(account.to_string());
self
}
pub fn and_account(&mut self, account: &str) -> &mut Self {
self.in_account(account)
}
pub fn owned_by(&mut self, account: &str) -> &mut Self {
self.in_account(account)
}
pub fn in_any_account(&mut self) -> &mut Self {
self.in_account(WILD)
}
pub fn resource(&mut self, resource: Resource) -> &mut Self {
self.arn.resource = resource;
self
}
pub fn is(&mut self, resource: Resource) -> &mut Self {
self.resource(resource)
}
pub fn a(&mut self, resource: Resource) -> &mut Self {
self.resource(resource)
}
pub fn any_resource(&mut self) -> &mut Self {
self.arn.resource = Resource::Any;
self
}
pub fn for_any_resource(&mut self) -> &mut Self {
self.any_resource()
}
pub fn build(&self) -> Result<ARN, ArnError> {
let new_arn = self.arn.clone();
new_arn.validate().map(|_| new_arn)
}
}
pub mod cognito;
pub mod iam;
pub mod lambda;
pub mod s3;
#[cfg(test)]
mod tests {
use super::{ArnBuilder, ResourceBuilder};
#[test]
fn test_s3_bucket() {
let arn = ArnBuilder::new("s3")
.resource(ResourceBuilder::new("my-bucket").build().unwrap())
.build()
.unwrap();
assert_eq!(arn.to_string(), "arn:aws:s3:::my-bucket");
}
#[test]
fn test_lambda_layer() {
let arn = ArnBuilder::new("lambda")
.resource(
ResourceBuilder::new("my-layer")
.is_a("layer")
.with_version(3)
.build()
.unwrap(),
)
.in_region("us-east-2")
.owned_by("123456789012")
.build()
.unwrap();
assert_eq!(
arn.to_string(),
"arn:aws:lambda:us-east-2:123456789012:layer:my-layer:3"
);
}
}