The Region where replication occurs.
+ pub region: Option,
+ /// Can be an ARN
, Key ID
, or Alias
.
+ pub kms_key_id: Option,
+ /// The status can be InProgress
, Failed
, or InSync
.
+ pub status: Option,
+ /// Status message such as "Secret with this name already exists in this region".
+ pub status_message: Option,
+ /// The date that the secret was last accessed in the Region. This field is omitted if the secret has never been retrieved in the Region.
+ pub last_accessed_date: Option,
+}
+
+impl From for ReplicationStatusType {
+ fn from(value: ReplicationStatusTypeDef) -> Self {
+ ReplicationStatusType::builder()
+ .set_region(value.region)
+ .set_kms_key_id(value.kms_key_id)
+ .set_status(value.status.map(Into::into))
+ .set_last_accessed_date(value.last_accessed_date.map(Into::into))
+ .set_status_message(value.status_message)
+ .build()
+ }
+}
+
+impl From<&ReplicationStatusType> for ReplicationStatusTypeDef {
+ fn from(value: &ReplicationStatusType) -> Self {
+ ReplicationStatusTypeDef {
+ region: value.region().map(String::from),
+ kms_key_id: value.kms_key_id().map(String::from),
+ status: value.status().map(Into::into),
+ status_message: value.status_message().map(String::from),
+ last_accessed_date: value.last_accessed_date().map(|i| (*i).try_into().unwrap()),
+ }
+ }
+}
+
+#[serde_as]
+#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, Debug, Hash, Serialize, Deserialize)]
+/// Status type
+pub enum StatusTypeDef {
+ #[allow(missing_docs)] // documentation missing in model
+ Failed,
+ #[allow(missing_docs)] // documentation missing in model
+ InProgress,
+ #[allow(missing_docs)] // documentation missing in model
+ InSync,
+}
+
+impl From for StatusType {
+ fn from(value: StatusTypeDef) -> Self {
+ match value {
+ StatusTypeDef::Failed => StatusType::Failed,
+ StatusTypeDef::InProgress => StatusType::InProgress,
+ StatusTypeDef::InSync => StatusType::InSync,
+ }
+ }
+}
+
+impl From<&StatusType> for StatusTypeDef {
+ fn from(value: &StatusType) -> Self {
+ match value {
+ StatusType::Failed => StatusTypeDef::Failed,
+ StatusType::InProgress => StatusTypeDef::InProgress,
+ StatusType::InSync => StatusTypeDef::InSync,
+ _ => panic!("Invalid value for StatusTypeDef: {}", value),
+ }
+ }
+}
+
+impl From for DescribeSecretOutputDef {
+ fn from(input: DescribeSecretOutput) -> Self {
+ Self::new(input)
+ }
+}
diff --git a/aws_secretsmanager_caching/src/output.rs b/aws_secretsmanager_caching/src/output/get_secret_value_output.rs
similarity index 74%
rename from aws_secretsmanager_caching/src/output.rs
rename to aws_secretsmanager_caching/src/output/get_secret_value_output.rs
index a8ecab4..7716a95 100644
--- a/aws_secretsmanager_caching/src/output.rs
+++ b/aws_secretsmanager_caching/src/output/get_secret_value_output.rs
@@ -1,7 +1,7 @@
use aws_sdk_secretsmanager::operation::get_secret_value::GetSecretValueOutput;
use aws_smithy_types::base64;
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use serde_with::{serde_as, DeserializeAs, SerializeAs, TimestampSecondsWithFrac};
+use serde::{Deserialize, Serialize, Serializer};
+use serde_with::{serde_as, TimestampSecondsWithFrac};
use std::convert::TryFrom;
use std::time::SystemTime;
@@ -61,12 +61,6 @@ impl GetSecretValueOutputDef {
}
}
-impl From for GetSecretValueOutputDef {
- fn from(input: GetSecretValueOutput) -> Self {
- Self::new(input)
- }
-}
-
/// Copy of the remote AWS SDK Blob type.
#[serde_as]
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Deserialize)]
@@ -96,40 +90,8 @@ impl Serialize for BlobDef {
}
}
-/// Copy of the remote aws_smithy_types::DateTime type.
-#[serde_as]
-#[derive(Serialize, Deserialize, Debug)]
-#[serde(remote = "::aws_smithy_types::DateTime")]
-pub struct DateTimeDef {
- #[serde(getter = "::aws_smithy_types::DateTime::secs")]
- seconds: i64,
- #[serde(getter = "::aws_smithy_types::DateTime::subsec_nanos")]
- subsecond_nanos: u32,
-}
-
-impl SerializeAs<::aws_smithy_types::DateTime> for DateTimeDef {
- fn serialize_as(
- source: &::aws_smithy_types::DateTime,
- serializer: S,
- ) -> Result
- where
- S: Serializer,
- {
- DateTimeDef::serialize(source, serializer)
- }
-}
-
-impl<'de> DeserializeAs<'de, ::aws_smithy_types::DateTime> for DateTimeDef {
- fn deserialize_as(deserializer: D) -> Result<::aws_smithy_types::DateTime, D::Error>
- where
- D: Deserializer<'de>,
- {
- DateTimeDef::deserialize(deserializer)
- }
-}
-
-impl From for ::aws_smithy_types::DateTime {
- fn from(def: DateTimeDef) -> ::aws_smithy_types::DateTime {
- ::aws_smithy_types::DateTime::from_secs_and_nanos(def.seconds, def.subsecond_nanos)
+impl From for GetSecretValueOutputDef {
+ fn from(input: GetSecretValueOutput) -> Self {
+ Self::new(input)
}
}
diff --git a/aws_secretsmanager_caching/src/output/mod.rs b/aws_secretsmanager_caching/src/output/mod.rs
new file mode 100644
index 0000000..cc52c7d
--- /dev/null
+++ b/aws_secretsmanager_caching/src/output/mod.rs
@@ -0,0 +1,5 @@
+mod describe_secret_output;
+mod get_secret_value_output;
+
+pub use describe_secret_output::DescribeSecretOutputDef;
+pub use get_secret_value_output::GetSecretValueOutputDef;
diff --git a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs
index df405dd..ed36452 100644
--- a/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs
+++ b/aws_secretsmanager_caching/src/secret_store/memory_store/mod.rs
@@ -1,6 +1,6 @@
mod cache;
-use crate::output::GetSecretValueOutputDef;
+use crate::output::{DescribeSecretOutputDef, GetSecretValueOutputDef};
use self::cache::Cache;
@@ -33,10 +33,26 @@ impl GSVValue {
}
}
+#[derive(Debug, Clone)]
+struct DescribeValue {
+ value: DescribeSecretOutputDef,
+ last_retrieved_at: Instant,
+}
+
+impl DescribeValue {
+ fn new(value: DescribeSecretOutputDef) -> Self {
+ Self {
+ value,
+ last_retrieved_at: Instant::now(),
+ }
+ }
+}
+
#[derive(Debug, Clone)]
/// In-memory secret store using an time and space bound cache
pub struct MemoryStore {
gsv_cache: Cache,
+ describe_cache: Cache,
ttl: Duration,
}
@@ -51,6 +67,7 @@ impl MemoryStore {
pub fn new(max_size: NonZeroUsize, ttl: Duration) -> Self {
Self {
gsv_cache: Cache::new(max_size),
+ describe_cache: Cache::new(max_size),
ttl,
}
}
@@ -94,6 +111,30 @@ impl SecretStore for MemoryStore {
Ok(())
}
+
+ fn describe_secret<'a>(
+ &'a self,
+ secret_id: &'a str,
+ ) -> Result {
+ match self.describe_cache.get(secret_id) {
+ Some(describe) if describe.last_retrieved_at.elapsed() > self.ttl => {
+ Err(SecretStoreError::DescribeCacheExpired)
+ }
+ Some(describe) => Ok(describe.clone().value),
+ None => Err(SecretStoreError::ResourceNotFound),
+ }
+ }
+
+ fn write_describe_secret(
+ &mut self,
+ secret_id: String,
+ data: DescribeSecretOutputDef,
+ ) -> Result<(), SecretStoreError> {
+ self.describe_cache
+ .insert(secret_id, DescribeValue::new(data));
+
+ Ok(())
+ }
}
/// Write the secret value to the store
diff --git a/aws_secretsmanager_caching/src/secret_store/mod.rs b/aws_secretsmanager_caching/src/secret_store/mod.rs
index f566727..2593db3 100644
--- a/aws_secretsmanager_caching/src/secret_store/mod.rs
+++ b/aws_secretsmanager_caching/src/secret_store/mod.rs
@@ -4,7 +4,7 @@ pub use memory_store::MemoryStore;
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt::Debug};
-use crate::output::GetSecretValueOutputDef;
+use crate::output::{DescribeSecretOutputDef, GetSecretValueOutputDef};
/// Response of the GetSecretValue API
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -29,6 +29,19 @@ pub trait SecretStore: Debug + Send + Sync {
version_stage: Option,
data: GetSecretValueOutputDef,
) -> Result<(), SecretStoreError>;
+
+ /// Get secret metadata from the cache
+ fn describe_secret<'a>(
+ &'a self,
+ secret_id: &'a str,
+ ) -> Result;
+
+ /// Write secret metadata to the cache
+ fn write_describe_secret(
+ &mut self,
+ secret_id: String,
+ data: DescribeSecretOutputDef,
+ ) -> Result<(), SecretStoreError>;
}
/// All possible error types
@@ -42,6 +55,10 @@ pub enum SecretStoreError {
#[error("cache expired")]
CacheExpired(Box),
+ /// Describe Secret cache TTL expired
+ #[error("cache expired")]
+ DescribeCacheExpired,
+
/// An unexpected error occurred
#[error("unhandled error {0:?}")]
Unhandled(#[source] Box),