From e9d48164428f2ce5609d5dc923a13f5f6999288a Mon Sep 17 00:00:00 2001 From: raf Date: Thu, 22 Jun 2023 11:57:12 +0100 Subject: [PATCH 1/2] fix: broken ssm param update, updated error message --- moto/ssm/exceptions.py | 10 ++++++ moto/ssm/models.py | 6 +++- moto/ssm/responses.py | 8 ++--- tests/test_ssm/test_ssm_boto3.py | 57 +++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/moto/ssm/exceptions.py b/moto/ssm/exceptions.py index 4c6b69ca6..14bb94c68 100644 --- a/moto/ssm/exceptions.py +++ b/moto/ssm/exceptions.py @@ -139,3 +139,13 @@ class ParameterMaxVersionLimitExceeded(JsonRESTError): def __init__(self, message: str): super().__init__("ParameterMaxVersionLimitExceeded", message) + + +class ParameterAlreadyExists(JsonRESTError): + code = 400 + + def __init__(self): + super().__init__( + "ParameterAlreadyExists", + "The parameter already exists. To overwrite this value, set the overwrite option in the request to true.", + ) diff --git a/moto/ssm/models.py b/moto/ssm/models.py index 2902fd04c..3a9f66550 100644 --- a/moto/ssm/models.py +++ b/moto/ssm/models.py @@ -1899,7 +1899,11 @@ class SimpleSystemManagerBackend(BaseBackend): ) raise ValidationException(invalid_prefix_error) - if not _valid_parameter_type(parameter_type): + if ( + not _valid_parameter_type(parameter_type) + and not overwrite + and name not in self._parameters + ): raise ValidationException( f"1 validation error detected: Value '{parameter_type}' at 'type' failed to satisfy constraint: Member must satisfy enum value set: [SecureString, StringList, String]", ) diff --git a/moto/ssm/responses.py b/moto/ssm/responses.py index 7d7b9d3d2..43476aadb 100644 --- a/moto/ssm/responses.py +++ b/moto/ssm/responses.py @@ -2,7 +2,7 @@ import json from typing import Any, Dict, Tuple, Union from moto.core.responses import BaseResponse -from .exceptions import ValidationException +from .exceptions import ValidationException, ParameterAlreadyExists from .models import ssm_backends, SimpleSystemManagerBackend @@ -286,11 +286,7 @@ class SimpleSystemManagerResponse(BaseResponse): ) if result is None: - error = { - "__type": "ParameterAlreadyExists", - "message": f"Parameter {name} already exists.", - } - return json.dumps(error), dict(status=400) + raise ParameterAlreadyExists response = {"Version": result} return json.dumps(response) diff --git a/tests/test_ssm/test_ssm_boto3.py b/tests/test_ssm/test_ssm_boto3.py index daf6a73a9..6c227ee8d 100644 --- a/tests/test_ssm/test_ssm_boto3.py +++ b/tests/test_ssm/test_ssm_boto3.py @@ -253,7 +253,7 @@ def test_put_parameter(name): except botocore.exceptions.ClientError as err: err.operation_name.should.equal("PutParameter") err.response["Error"]["Message"].should.equal( - f"Parameter {name} already exists." + "The parameter already exists. To overwrite this value, set the overwrite option in the request to true." ) response = client.get_parameters(Names=[name], WithDecryption=False) @@ -431,6 +431,61 @@ def test_put_parameter_invalid_type(): ) +@mock_ssm +def test_update_parameter(): + # Setup + client = boto3.client("ssm", "us-east-1") + param_name = "test_param" + updated_value = "UpdatedValue" + client.put_parameter( + Description="Description", + Name=param_name, + Type="String", + Value="Value", + ) + + # Execute + response = client.put_parameter( + Name=param_name, + Overwrite=True, + Value=updated_value, + ) + new_param = client.get_parameter(Name=param_name) + + # Verify + assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 + assert new_param["Parameter"]["Value"] == updated_value + + +@mock_ssm +def test_update_parameter_already_exists_error(): + # Setup + client = boto3.client("ssm", "us-east-1") + client.put_parameter( + Description="Description", + Name="Name", + Type="String", + Value="Value", + ) + + # Execute + with pytest.raises(ClientError) as exc: + client.put_parameter( + Name="Name", + Value="UpdatedValue", + ) + + # Verify + ex = exc.value + assert ex.operation_name.should.equal("PutParameter") + assert ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + assert ex.response["Error"]["Code"] == "ParameterAlreadyExists" + assert ( + ex.response["Error"]["Message"] + == "The parameter already exists. To overwrite this value, set the overwrite option in the request to true." + ) + + @mock_ssm def test_get_parameter(): client = boto3.client("ssm", region_name="us-east-1") From 103d6a9293e3bf9217c98525f05087c2f2a2d56d Mon Sep 17 00:00:00 2001 From: raf Date: Thu, 22 Jun 2023 12:54:34 +0100 Subject: [PATCH 2/2] chore: mypy --- moto/ssm/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moto/ssm/exceptions.py b/moto/ssm/exceptions.py index 14bb94c68..29813c22d 100644 --- a/moto/ssm/exceptions.py +++ b/moto/ssm/exceptions.py @@ -144,7 +144,7 @@ class ParameterMaxVersionLimitExceeded(JsonRESTError): class ParameterAlreadyExists(JsonRESTError): code = 400 - def __init__(self): + def __init__(self) -> None: super().__init__( "ParameterAlreadyExists", "The parameter already exists. To overwrite this value, set the overwrite option in the request to true.",