dynoxide/actions/
tag_resource.rs1use crate::actions::helpers;
2use crate::errors::{DynoxideError, Result};
3use crate::storage_backend::StorageBackend;
4use crate::types::Tag;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Default, Deserialize)]
8pub struct TagResourceRequest {
9 #[serde(rename = "ResourceArn", default)]
10 pub resource_arn: Option<String>,
11 #[serde(rename = "Tags", default)]
12 pub tags: Vec<Tag>,
13}
14
15#[derive(Debug, Default, Serialize)]
16pub struct TagResourceResponse {}
17
18pub async fn execute<S: StorageBackend>(
19 storage: &S,
20 request: TagResourceRequest,
21) -> Result<TagResourceResponse> {
22 let arn = request.resource_arn.as_deref().unwrap_or("");
23 if arn.is_empty() {
24 return Err(DynoxideError::ValidationException(
25 "Invalid TableArn".to_string(),
26 ));
27 }
28 let table_name = helpers::parse_table_name_from_arn(arn)?;
29
30 if request.tags.is_empty() {
32 return Err(DynoxideError::ValidationException(
33 "Atleast one Tag needs to be provided as Input.".to_string(),
34 ));
35 }
36 for tag in &request.tags {
37 validate_tag(tag)?;
38 }
39
40 if !storage.table_exists(table_name).await? {
42 return Err(DynoxideError::ResourceNotFoundException(format!(
43 "Requested resource not found: ResourcArn: {arn} not found"
44 )));
45 }
46
47 storage.set_tags(table_name, &request.tags).await?;
48
49 Ok(TagResourceResponse {})
50}
51
52fn validate_tag(tag: &Tag) -> Result<()> {
53 if tag.key.is_empty() || tag.key.len() > 128 {
54 return Err(DynoxideError::ValidationException(
55 "One or more parameter values were invalid: \
56 Tag key must be between 1 and 128 characters"
57 .to_string(),
58 ));
59 }
60 if tag.value.len() > 256 {
61 return Err(DynoxideError::ValidationException(
62 "One or more parameter values were invalid: \
63 Tag value must be between 0 and 256 characters"
64 .to_string(),
65 ));
66 }
67 Ok(())
68}