use super::*;
impl RdsService {
pub(super) fn create_db_parameter_group(
&self,
request: &AwsRequest,
) -> Result<AwsResponse, AwsServiceError> {
let db_parameter_group_name = required_query_param(request, "DBParameterGroupName")?;
let db_parameter_group_family = required_query_param(request, "DBParameterGroupFamily")?;
let description = required_query_param(request, "Description")?;
if db_parameter_group_name.starts_with("default.") {
return Err(AwsServiceError::aws_error(
StatusCode::BAD_REQUEST,
"InvalidParameterValue",
"DBParameterGroupName cannot start with the reserved 'default.' prefix",
));
}
let mut accounts = self.state.write();
let state = accounts.get_or_create(&request.account_id);
if state
.parameter_groups
.contains_key(&db_parameter_group_name)
{
return Err(AwsServiceError::aws_error(
StatusCode::CONFLICT,
"DBParameterGroupAlreadyExists",
format!("DBParameterGroup {db_parameter_group_name} already exists."),
));
}
let db_parameter_group_arn = state.db_parameter_group_arn(&db_parameter_group_name);
let tags = parse_tags(request)?;
let parameter_group = DbParameterGroup {
db_parameter_group_name: db_parameter_group_name.clone(),
db_parameter_group_arn,
db_parameter_group_family,
description,
parameters: std::collections::BTreeMap::new(),
parameter_apply_methods: std::collections::BTreeMap::new(),
tags,
};
state
.parameter_groups
.insert(db_parameter_group_name.clone(), parameter_group.clone());
let arn = parameter_group.db_parameter_group_arn.clone();
drop(accounts);
self.emit_event(
RdsSourceType::DbParameterGroup,
&db_parameter_group_name,
&arn,
"RDS-EVENT-0179",
&["creation"],
"DB parameter group created",
);
Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml(
"CreateDBParameterGroup",
RDS_NS,
&format!(
"<DBParameterGroup>{}</DBParameterGroup>",
db_parameter_group_xml(¶meter_group)
),
&request.request_id,
),
))
}
pub(super) fn describe_db_parameter_groups(
&self,
request: &AwsRequest,
) -> Result<AwsResponse, AwsServiceError> {
let db_parameter_group_name = optional_query_param(request, "DBParameterGroupName");
let marker = optional_query_param(request, "Marker");
let max_records = optional_query_param(request, "MaxRecords");
let accounts = self.state.read();
let empty = RdsState::new(&request.account_id, &request.region);
let state = accounts.get(&request.account_id).unwrap_or(&empty);
if let Some(name) = db_parameter_group_name {
let pg = state.parameter_groups.get(&name).ok_or_else(|| {
AwsServiceError::aws_error(
StatusCode::NOT_FOUND,
"DBParameterGroupNotFound",
format!("DBParameterGroup {} not found.", name),
)
})?;
return Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml(
"DescribeDBParameterGroups", RDS_NS,
&format!(
"<DBParameterGroups><DBParameterGroup>{}</DBParameterGroup></DBParameterGroups>",
db_parameter_group_xml(pg)
),
&request.request_id,
),
));
}
let mut parameter_groups: Vec<DbParameterGroup> =
state.parameter_groups.values().cloned().collect();
parameter_groups.sort_by(|a, b| a.db_parameter_group_name.cmp(&b.db_parameter_group_name));
let paginated = paginate(parameter_groups, marker, max_records, |pg| {
&pg.db_parameter_group_name
})?;
let marker_xml = paginated
.next_marker
.as_ref()
.map(|m| format!("<Marker>{}</Marker>", xml_escape(m)))
.unwrap_or_default();
let body = paginated
.items
.iter()
.map(|pg| {
format!(
"<DBParameterGroup>{}</DBParameterGroup>",
db_parameter_group_xml(pg)
)
})
.collect::<Vec<_>>()
.join("");
Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml(
"DescribeDBParameterGroups",
RDS_NS,
&format!(
"<DBParameterGroups>{}</DBParameterGroups>{}",
body, marker_xml
),
&request.request_id,
),
))
}
pub(super) fn delete_db_parameter_group(
&self,
request: &AwsRequest,
) -> Result<AwsResponse, AwsServiceError> {
let db_parameter_group_name = required_query_param(request, "DBParameterGroupName")?;
let arn = {
let mut accounts = self.state.write();
let state = accounts.get_or_create(&request.account_id);
if db_parameter_group_name.starts_with("default.") {
return Err(AwsServiceError::aws_error(
StatusCode::BAD_REQUEST,
"InvalidDBParameterGroupState",
"Cannot delete default parameter groups.",
));
}
let removed = state
.parameter_groups
.remove(&db_parameter_group_name)
.ok_or_else(|| {
AwsServiceError::aws_error(
StatusCode::NOT_FOUND,
"DBParameterGroupNotFound",
format!("DBParameterGroup {db_parameter_group_name} not found."),
)
})?;
removed.db_parameter_group_arn
};
self.emit_event(
RdsSourceType::DbParameterGroup,
&db_parameter_group_name,
&arn,
"RDS-EVENT-0064",
&["deletion"],
"DB parameter group deleted",
);
Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml("DeleteDBParameterGroup", RDS_NS, "", &request.request_id),
))
}
pub(super) fn modify_db_parameter_group(
&self,
request: &AwsRequest,
) -> Result<AwsResponse, AwsServiceError> {
let db_parameter_group_name = required_query_param(request, "DBParameterGroupName")?;
let parsed_params = parse_db_parameter_members(request);
let mut accounts = self.state.write();
let state = accounts.get_or_create(&request.account_id);
let parameter_group = state
.parameter_groups
.get_mut(&db_parameter_group_name)
.ok_or_else(|| {
AwsServiceError::aws_error(
StatusCode::NOT_FOUND,
"DBParameterGroupNotFound",
format!("DBParameterGroup {db_parameter_group_name} not found."),
)
})?;
if let Some(new_description) = optional_query_param(request, "Description") {
parameter_group.description = new_description;
}
for param in parsed_params {
parameter_group
.parameters
.insert(param.name.clone(), param.value);
parameter_group
.parameter_apply_methods
.insert(param.name, param.apply_method);
}
let parameter_group_clone = parameter_group.clone();
let arn = parameter_group_clone.db_parameter_group_arn.clone();
drop(accounts);
self.emit_event(
RdsSourceType::DbParameterGroup,
&db_parameter_group_name,
&arn,
"RDS-EVENT-0037",
&["configuration change"],
"DB parameter group modified",
);
Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml(
"ModifyDBParameterGroup",
RDS_NS,
&format!(
"<DBParameterGroupName>{}</DBParameterGroupName>",
xml_escape(¶meter_group_clone.db_parameter_group_name)
),
&request.request_id,
),
))
}
pub(super) fn describe_db_parameters_real(
&self,
request: &AwsRequest,
) -> Result<AwsResponse, AwsServiceError> {
let db_parameter_group_name = required_query_param(request, "DBParameterGroupName")?;
let source_filter = optional_query_param(request, "Source");
let accounts = self.state.read();
let state = match accounts.get(&request.account_id) {
Some(s) => s,
None => {
return Err(AwsServiceError::aws_error(
StatusCode::NOT_FOUND,
"DBParameterGroupNotFound",
format!("DBParameterGroup {db_parameter_group_name} not found."),
));
}
};
let parameter_group = state
.parameter_groups
.get(&db_parameter_group_name)
.ok_or_else(|| {
AwsServiceError::aws_error(
StatusCode::NOT_FOUND,
"DBParameterGroupNotFound",
format!("DBParameterGroup {db_parameter_group_name} not found."),
)
})?;
let source = source_filter.as_deref();
let include_user = source.is_none_or(|s| s == "user");
let include_engine_default = source.is_none_or(|s| s == "engine-default");
let mut members_xml = String::new();
if include_user {
for (name, value) in ¶meter_group.parameters {
let apply_method = parameter_group
.parameter_apply_methods
.get(name)
.map(String::as_str)
.unwrap_or("immediate");
members_xml.push_str(&render_user_parameter_xml(name, value, apply_method));
}
}
if include_engine_default {
for default in
crate::state::engine_default_parameters(¶meter_group.db_parameter_group_family)
{
if parameter_group.parameters.contains_key(default.name) {
continue;
}
members_xml.push_str(&render_engine_default_parameter_xml(default));
}
}
let body = format!(" <Parameters>\n{members_xml} </Parameters>");
Ok(AwsResponse::xml(
StatusCode::OK,
query_response_xml("DescribeDBParameters", RDS_NS, &body, &request.request_id),
))
}
}