SSM: fix overwrite preserving non-indicated values (#7066)
This commit is contained in:
parent
3c10fb12f0
commit
807dca6e50
@ -2106,6 +2106,24 @@ class SimpleSystemManagerBackend(BaseBackend):
|
||||
self._check_for_parameter_version_limit_exception(name)
|
||||
previous_parameter_versions.pop(0)
|
||||
|
||||
# Ensure all the previous values that we didn't overwrite are preserved
|
||||
value = value if value is not None else previous_parameter.value
|
||||
description = (
|
||||
description
|
||||
if description is not None
|
||||
else previous_parameter.description
|
||||
)
|
||||
allowed_pattern = (
|
||||
allowed_pattern
|
||||
if allowed_pattern is not None
|
||||
else previous_parameter.allowed_pattern
|
||||
)
|
||||
keyid = keyid if keyid is not None else previous_parameter.keyid
|
||||
tags = tags if tags is not None else previous_parameter.tags
|
||||
data_type = (
|
||||
data_type if data_type is not None else previous_parameter.data_type
|
||||
)
|
||||
|
||||
last_modified_date = time.time()
|
||||
self._parameters[name].append(
|
||||
Parameter(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
from typing import Any, Dict, Tuple, Union
|
||||
import warnings
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from .exceptions import ValidationException, ParameterAlreadyExists
|
||||
@ -270,9 +271,21 @@ class SimpleSystemManagerResponse(BaseResponse):
|
||||
allowed_pattern = self._get_param("AllowedPattern")
|
||||
keyid = self._get_param("KeyId")
|
||||
overwrite = self._get_param("Overwrite", False)
|
||||
tags = self._get_param("Tags", [])
|
||||
tags = self._get_param("Tags")
|
||||
data_type = self._get_param("DataType", "text")
|
||||
|
||||
# To be implemented arguments of put_parameter
|
||||
tier = self._get_param("Tier")
|
||||
if tier is not None:
|
||||
warnings.warn(
|
||||
"Tier configuration option is not yet implemented. Discarding."
|
||||
)
|
||||
policies = self._get_param("Policies")
|
||||
if policies is not None:
|
||||
warnings.warn(
|
||||
"Policies configuration option is not yet implemented. Discarding."
|
||||
)
|
||||
|
||||
result = self.ssm_backend.put_parameter(
|
||||
name,
|
||||
description,
|
||||
|
@ -2,13 +2,15 @@ import datetime
|
||||
import re
|
||||
import string
|
||||
import uuid
|
||||
from unittest.mock import patch, Mock
|
||||
from unittest import SkipTest
|
||||
|
||||
import boto3
|
||||
import botocore.exceptions
|
||||
from botocore.exceptions import ClientError
|
||||
import pytest
|
||||
|
||||
from moto import mock_ec2, mock_ssm
|
||||
from moto import mock_ec2, mock_ssm, settings
|
||||
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
||||
from moto.ssm.models import PARAMETER_VERSION_LIMIT, PARAMETER_HISTORY_MAX_RESULTS
|
||||
from tests import EXAMPLE_AMI_ID
|
||||
@ -262,6 +264,7 @@ def test_put_parameter(name):
|
||||
)
|
||||
new_data_type = "aws:ec2:image"
|
||||
|
||||
# Cannot have tags and overwrite at the same time
|
||||
with pytest.raises(ClientError) as ex:
|
||||
response = client.put_parameter(
|
||||
Name=name,
|
||||
@ -301,6 +304,157 @@ def test_put_parameter(name):
|
||||
)
|
||||
|
||||
|
||||
@mock_ssm
|
||||
def test_put_parameter_unimplemented_parameters():
|
||||
"""
|
||||
Test to ensure coverage of unimplemented parameters. Remove for appropriate tests
|
||||
once implemented
|
||||
"""
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Can't test for warning logs in server mode")
|
||||
|
||||
mock_warn = Mock()
|
||||
with patch("warnings.warn", mock_warn):
|
||||
# Ensure that the ssm parameters are still working with the Mock
|
||||
client = boto3.client("ssm", region_name="us-east-1")
|
||||
name = "my-param"
|
||||
response = client.put_parameter(
|
||||
Name=name,
|
||||
Description="A test parameter",
|
||||
Value="value",
|
||||
Type="String",
|
||||
Tier="Advanced",
|
||||
Policies="No way fam",
|
||||
)
|
||||
|
||||
assert response["Version"] == 1
|
||||
|
||||
response = client.get_parameters(Names=[name], WithDecryption=False)
|
||||
|
||||
assert len(response["Parameters"]) == 1
|
||||
assert response["Parameters"][0]["Name"] == name
|
||||
assert response["Parameters"][0]["Value"] == "value"
|
||||
assert response["Parameters"][0]["Type"] == "String"
|
||||
assert response["Parameters"][0]["Version"] == 1
|
||||
assert response["Parameters"][0]["DataType"] == "text"
|
||||
assert isinstance(
|
||||
response["Parameters"][0]["LastModifiedDate"], datetime.datetime
|
||||
)
|
||||
assert response["Parameters"][0]["ARN"] == (
|
||||
f"arn:aws:ssm:us-east-1:{ACCOUNT_ID}:parameter/{name}"
|
||||
)
|
||||
|
||||
# We got the argument warnings
|
||||
mock_warn.assert_any_call(
|
||||
"Tier configuration option is not yet implemented. Discarding."
|
||||
)
|
||||
mock_warn.assert_any_call(
|
||||
"Policies configuration option is not yet implemented. Discarding."
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["test", "my-cool-parameter"])
|
||||
@mock_ssm
|
||||
def test_put_parameter_overwrite_preserves_metadata(name):
|
||||
test_tag_key = "TestKey"
|
||||
test_tag_value = "TestValue"
|
||||
test_description = "A test parameter"
|
||||
test_pattern = ".*"
|
||||
test_key_id = "someKeyId"
|
||||
client = boto3.client("ssm", region_name="us-east-1")
|
||||
response = client.put_parameter(
|
||||
Name=name,
|
||||
Description=test_description,
|
||||
Value="value",
|
||||
Type="String",
|
||||
Tags=[
|
||||
{"Key": test_tag_key, "Value": test_tag_value},
|
||||
],
|
||||
AllowedPattern=test_pattern,
|
||||
KeyId=test_key_id,
|
||||
# TODO: add tier and policies support
|
||||
)
|
||||
|
||||
assert response["Version"] == 1
|
||||
|
||||
response = client.get_parameters(Names=[name], WithDecryption=False)
|
||||
|
||||
assert len(response["Parameters"]) == 1
|
||||
assert response["Parameters"][0]["Name"] == name
|
||||
assert response["Parameters"][0]["Value"] == "value"
|
||||
assert response["Parameters"][0]["Type"] == "String"
|
||||
assert response["Parameters"][0]["Version"] == 1
|
||||
assert response["Parameters"][0]["DataType"] == "text"
|
||||
assert isinstance(response["Parameters"][0]["LastModifiedDate"], datetime.datetime)
|
||||
assert response["Parameters"][0]["ARN"] == (
|
||||
f"arn:aws:ssm:us-east-1:{ACCOUNT_ID}:parameter/{name}"
|
||||
)
|
||||
initial_modification_date = response["Parameters"][0]["LastModifiedDate"]
|
||||
|
||||
# Verify that the tag got set
|
||||
response = client.list_tags_for_resource(ResourceType="Parameter", ResourceId=name)
|
||||
|
||||
assert len(response["TagList"]) == 1
|
||||
assert response["TagList"][0]["Key"] == test_tag_key
|
||||
assert response["TagList"][0]["Value"] == test_tag_value
|
||||
|
||||
# Verify description is set
|
||||
response = client.describe_parameters(
|
||||
ParameterFilters=[
|
||||
{
|
||||
"Key": "Name",
|
||||
"Option": "Equals",
|
||||
"Values": [name],
|
||||
},
|
||||
]
|
||||
)
|
||||
assert len(response["Parameters"]) == 1
|
||||
assert response["Parameters"][0]["Description"] == test_description
|
||||
assert response["Parameters"][0]["AllowedPattern"] == test_pattern
|
||||
assert response["Parameters"][0]["KeyId"] == test_key_id
|
||||
|
||||
# Overwrite just the value
|
||||
response = client.put_parameter(Name=name, Value="value 2", Overwrite=True)
|
||||
|
||||
assert response["Version"] == 2
|
||||
|
||||
response = client.get_parameters(Names=[name], WithDecryption=False)
|
||||
|
||||
assert len(response["Parameters"]) == 1
|
||||
assert response["Parameters"][0]["Name"] == name
|
||||
assert response["Parameters"][0]["Value"] == "value 2"
|
||||
assert response["Parameters"][0]["Type"] == "String"
|
||||
assert response["Parameters"][0]["Version"] == 2
|
||||
assert response["Parameters"][0]["DataType"] == "text"
|
||||
assert response["Parameters"][0]["LastModifiedDate"] != initial_modification_date
|
||||
assert response["Parameters"][0]["ARN"] == (
|
||||
f"arn:aws:ssm:us-east-1:{ACCOUNT_ID}:parameter/{name}"
|
||||
)
|
||||
initial_modification_date = response["Parameters"][0]["LastModifiedDate"]
|
||||
|
||||
# Verify that tags are unchanged
|
||||
response = client.list_tags_for_resource(ResourceType="Parameter", ResourceId=name)
|
||||
|
||||
assert len(response["TagList"]) == 1
|
||||
assert response["TagList"][0]["Key"] == test_tag_key
|
||||
assert response["TagList"][0]["Value"] == test_tag_value
|
||||
|
||||
# Verify description is unchanged
|
||||
response = client.describe_parameters(
|
||||
ParameterFilters=[
|
||||
{
|
||||
"Key": "Name",
|
||||
"Option": "Equals",
|
||||
"Values": [name],
|
||||
},
|
||||
]
|
||||
)
|
||||
assert len(response["Parameters"]) == 1
|
||||
assert response["Parameters"][0]["Description"] == test_description
|
||||
assert response["Parameters"][0]["AllowedPattern"] == test_pattern
|
||||
assert response["Parameters"][0]["KeyId"] == test_key_id
|
||||
|
||||
|
||||
@mock_ssm
|
||||
def test_put_parameter_empty_string_value():
|
||||
client = boto3.client("ssm", region_name="us-east-1")
|
||||
|
Loading…
Reference in New Issue
Block a user