SSM: fix overwrite preserving non-indicated values (#7066)

This commit is contained in:
Justin Hanselman 2023-11-27 12:13:58 -07:00 committed by GitHub
parent 3c10fb12f0
commit 807dca6e50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 187 additions and 2 deletions

View File

@ -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(

View File

@ -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,

View File

@ -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")