enhancement(SSM): Add DataType attribute to SSM Parameters (#4232)
This commit is contained in:
parent
dc49232734
commit
58da62cc71
@ -55,6 +55,7 @@ class Parameter(BaseModel):
|
|||||||
keyid,
|
keyid,
|
||||||
last_modified_date,
|
last_modified_date,
|
||||||
version,
|
version,
|
||||||
|
data_type,
|
||||||
tags=None,
|
tags=None,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -64,6 +65,7 @@ class Parameter(BaseModel):
|
|||||||
self.keyid = keyid
|
self.keyid = keyid
|
||||||
self.last_modified_date = last_modified_date
|
self.last_modified_date = last_modified_date
|
||||||
self.version = version
|
self.version = version
|
||||||
|
self.data_type = data_type
|
||||||
self.tags = tags or []
|
self.tags = tags or []
|
||||||
self.labels = []
|
self.labels = []
|
||||||
|
|
||||||
@ -93,6 +95,7 @@ class Parameter(BaseModel):
|
|||||||
"Value": self.decrypt(self.value) if decrypt else self.value,
|
"Value": self.decrypt(self.value) if decrypt else self.value,
|
||||||
"Version": self.version,
|
"Version": self.version,
|
||||||
"LastModifiedDate": round(self.last_modified_date, 3),
|
"LastModifiedDate": round(self.last_modified_date, 3),
|
||||||
|
"DataType": self.data_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
if region:
|
if region:
|
||||||
@ -618,6 +621,14 @@ def _document_filter_match(filters, ssm_doc):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _valid_parameter_data_type(data_type):
|
||||||
|
"""
|
||||||
|
Parameter DataType field allows only `text` and `aws:ec2:image` values
|
||||||
|
|
||||||
|
"""
|
||||||
|
return data_type in ("text", "aws:ec2:image")
|
||||||
|
|
||||||
|
|
||||||
class SimpleSystemManagerBackend(BaseBackend):
|
class SimpleSystemManagerBackend(BaseBackend):
|
||||||
def __init__(self, region_name=None):
|
def __init__(self, region_name=None):
|
||||||
super(SimpleSystemManagerBackend, self).__init__()
|
super(SimpleSystemManagerBackend, self).__init__()
|
||||||
@ -1480,7 +1491,16 @@ class SimpleSystemManagerBackend(BaseBackend):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def put_parameter(
|
def put_parameter(
|
||||||
self, name, description, value, type, allowed_pattern, keyid, overwrite, tags,
|
self,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
allowed_pattern,
|
||||||
|
keyid,
|
||||||
|
overwrite,
|
||||||
|
tags,
|
||||||
|
data_type,
|
||||||
):
|
):
|
||||||
if not value:
|
if not value:
|
||||||
raise ValidationException(
|
raise ValidationException(
|
||||||
@ -1504,6 +1524,15 @@ class SimpleSystemManagerBackend(BaseBackend):
|
|||||||
"formed as a mix of letters, numbers and the following 3 symbols .-_"
|
"formed as a mix of letters, numbers and the following 3 symbols .-_"
|
||||||
)
|
)
|
||||||
raise ValidationException(invalid_prefix_error)
|
raise ValidationException(invalid_prefix_error)
|
||||||
|
|
||||||
|
if not _valid_parameter_data_type(data_type):
|
||||||
|
# The check of the existence of an AMI ID in the account for a parameter of DataType `aws:ec2:image`
|
||||||
|
# is not supported. The parameter will be created.
|
||||||
|
# https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-ec2-aliases.html
|
||||||
|
raise ValidationException(
|
||||||
|
f"The following data type is not supported: {data_type} (Data type names are all lowercase.)"
|
||||||
|
)
|
||||||
|
|
||||||
previous_parameter_versions = self._parameters[name]
|
previous_parameter_versions = self._parameters[name]
|
||||||
if len(previous_parameter_versions) == 0:
|
if len(previous_parameter_versions) == 0:
|
||||||
previous_parameter = None
|
previous_parameter = None
|
||||||
@ -1522,15 +1551,16 @@ class SimpleSystemManagerBackend(BaseBackend):
|
|||||||
last_modified_date = time.time()
|
last_modified_date = time.time()
|
||||||
self._parameters[name].append(
|
self._parameters[name].append(
|
||||||
Parameter(
|
Parameter(
|
||||||
name,
|
name=name,
|
||||||
value,
|
value=value,
|
||||||
type,
|
type=type,
|
||||||
description,
|
description=description,
|
||||||
allowed_pattern,
|
allowed_pattern=allowed_pattern,
|
||||||
keyid,
|
keyid=keyid,
|
||||||
last_modified_date,
|
last_modified_date=last_modified_date,
|
||||||
version,
|
version=version,
|
||||||
tags or [],
|
tags=tags or [],
|
||||||
|
data_type=data_type,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -277,9 +277,18 @@ class SimpleSystemManagerResponse(BaseResponse):
|
|||||||
keyid = self._get_param("KeyId")
|
keyid = self._get_param("KeyId")
|
||||||
overwrite = self._get_param("Overwrite", False)
|
overwrite = self._get_param("Overwrite", False)
|
||||||
tags = self._get_param("Tags", [])
|
tags = self._get_param("Tags", [])
|
||||||
|
data_type = self._get_param("DataType", "text")
|
||||||
|
|
||||||
result = self.ssm_backend.put_parameter(
|
result = self.ssm_backend.put_parameter(
|
||||||
name, description, value, type_, allowed_pattern, keyid, overwrite, tags
|
name,
|
||||||
|
description,
|
||||||
|
value,
|
||||||
|
type_,
|
||||||
|
allowed_pattern,
|
||||||
|
keyid,
|
||||||
|
overwrite,
|
||||||
|
tags,
|
||||||
|
data_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
if result is None:
|
if result is None:
|
||||||
|
@ -232,9 +232,8 @@ def test_get_parameters_by_path():
|
|||||||
@mock_ssm
|
@mock_ssm
|
||||||
def test_put_parameter(name):
|
def test_put_parameter(name):
|
||||||
client = boto3.client("ssm", region_name="us-east-1")
|
client = boto3.client("ssm", region_name="us-east-1")
|
||||||
|
|
||||||
response = client.put_parameter(
|
response = client.put_parameter(
|
||||||
Name=name, Description="A test parameter", Value="value", Type="String"
|
Name=name, Description="A test parameter", Value="value", Type="String",
|
||||||
)
|
)
|
||||||
|
|
||||||
response["Version"].should.equal(1)
|
response["Version"].should.equal(1)
|
||||||
@ -246,6 +245,7 @@ def test_put_parameter(name):
|
|||||||
response["Parameters"][0]["Value"].should.equal("value")
|
response["Parameters"][0]["Value"].should.equal("value")
|
||||||
response["Parameters"][0]["Type"].should.equal("String")
|
response["Parameters"][0]["Type"].should.equal("String")
|
||||||
response["Parameters"][0]["Version"].should.equal(1)
|
response["Parameters"][0]["Version"].should.equal(1)
|
||||||
|
response["Parameters"][0]["DataType"].should.equal("text")
|
||||||
response["Parameters"][0]["LastModifiedDate"].should.be.a(datetime.datetime)
|
response["Parameters"][0]["LastModifiedDate"].should.be.a(datetime.datetime)
|
||||||
response["Parameters"][0]["ARN"].should.equal(
|
response["Parameters"][0]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
|
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
|
||||||
@ -271,15 +271,21 @@ def test_put_parameter(name):
|
|||||||
response["Parameters"][0]["Value"].should.equal("value")
|
response["Parameters"][0]["Value"].should.equal("value")
|
||||||
response["Parameters"][0]["Type"].should.equal("String")
|
response["Parameters"][0]["Type"].should.equal("String")
|
||||||
response["Parameters"][0]["Version"].should.equal(1)
|
response["Parameters"][0]["Version"].should.equal(1)
|
||||||
|
response["Parameters"][0]["DataType"].should.equal("text")
|
||||||
response["Parameters"][0]["LastModifiedDate"].should.equal(
|
response["Parameters"][0]["LastModifiedDate"].should.equal(
|
||||||
initial_modification_date
|
initial_modification_date
|
||||||
)
|
)
|
||||||
response["Parameters"][0]["ARN"].should.equal(
|
response["Parameters"][0]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
|
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
|
||||||
)
|
)
|
||||||
|
new_data_type = "aws:ec2:image"
|
||||||
response = client.put_parameter(
|
response = client.put_parameter(
|
||||||
Name=name, Description="desc 3", Value="value 3", Type="String", Overwrite=True,
|
Name=name,
|
||||||
|
Description="desc 3",
|
||||||
|
Value="value 3",
|
||||||
|
Type="String",
|
||||||
|
Overwrite=True,
|
||||||
|
DataType=new_data_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
response["Version"].should.equal(2)
|
response["Version"].should.equal(2)
|
||||||
@ -292,6 +298,8 @@ def test_put_parameter(name):
|
|||||||
response["Parameters"][0]["Value"].should.equal("value 3")
|
response["Parameters"][0]["Value"].should.equal("value 3")
|
||||||
response["Parameters"][0]["Type"].should.equal("String")
|
response["Parameters"][0]["Type"].should.equal("String")
|
||||||
response["Parameters"][0]["Version"].should.equal(2)
|
response["Parameters"][0]["Version"].should.equal(2)
|
||||||
|
response["Parameters"][0]["DataType"].should_not.equal("text")
|
||||||
|
response["Parameters"][0]["DataType"].should.equal(new_data_type)
|
||||||
response["Parameters"][0]["LastModifiedDate"].should_not.equal(
|
response["Parameters"][0]["LastModifiedDate"].should_not.equal(
|
||||||
initial_modification_date
|
initial_modification_date
|
||||||
)
|
)
|
||||||
@ -394,12 +402,30 @@ def test_put_parameter_china():
|
|||||||
response["Version"].should.equal(1)
|
response["Version"].should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ssm
|
||||||
|
@pytest.mark.parametrize("bad_data_type", ["not_text", "not_ec2", "something weird"])
|
||||||
|
def test_put_parameter_invalid_data_type(bad_data_type):
|
||||||
|
client = boto3.client("ssm", region_name="us-east-1")
|
||||||
|
with pytest.raises(ClientError) as e:
|
||||||
|
client.put_parameter(
|
||||||
|
Name="test_name", Value="some_value", Type="String", DataType=bad_data_type
|
||||||
|
)
|
||||||
|
ex = e.value
|
||||||
|
ex.operation_name.should.equal("PutParameter")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain("ValidationException")
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
f"The following data type is not supported: {bad_data_type}"
|
||||||
|
" (Data type names are all lowercase.)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@mock_ssm
|
@mock_ssm
|
||||||
def test_get_parameter():
|
def test_get_parameter():
|
||||||
client = boto3.client("ssm", region_name="us-east-1")
|
client = boto3.client("ssm", region_name="us-east-1")
|
||||||
|
|
||||||
client.put_parameter(
|
client.put_parameter(
|
||||||
Name="test", Description="A test parameter", Value="value", Type="String"
|
Name="test", Description="A test parameter", Value="value", Type="String",
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.get_parameter(Name="test", WithDecryption=False)
|
response = client.get_parameter(Name="test", WithDecryption=False)
|
||||||
@ -407,6 +433,7 @@ def test_get_parameter():
|
|||||||
response["Parameter"]["Name"].should.equal("test")
|
response["Parameter"]["Name"].should.equal("test")
|
||||||
response["Parameter"]["Value"].should.equal("value")
|
response["Parameter"]["Value"].should.equal("value")
|
||||||
response["Parameter"]["Type"].should.equal("String")
|
response["Parameter"]["Type"].should.equal("String")
|
||||||
|
response["Parameter"]["DataType"].should.equal("text")
|
||||||
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
||||||
response["Parameter"]["ARN"].should.equal(
|
response["Parameter"]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/test".format(ACCOUNT_ID)
|
"arn:aws:ssm:us-east-1:{}:parameter/test".format(ACCOUNT_ID)
|
||||||
@ -418,10 +445,10 @@ def test_get_parameter_with_version_and_labels():
|
|||||||
client = boto3.client("ssm", region_name="us-east-1")
|
client = boto3.client("ssm", region_name="us-east-1")
|
||||||
|
|
||||||
client.put_parameter(
|
client.put_parameter(
|
||||||
Name="test-1", Description="A test parameter", Value="value", Type="String"
|
Name="test-1", Description="A test parameter", Value="value", Type="String",
|
||||||
)
|
)
|
||||||
client.put_parameter(
|
client.put_parameter(
|
||||||
Name="test-2", Description="A test parameter", Value="value", Type="String"
|
Name="test-2", Description="A test parameter", Value="value", Type="String",
|
||||||
)
|
)
|
||||||
|
|
||||||
client.label_parameter_version(
|
client.label_parameter_version(
|
||||||
@ -433,6 +460,7 @@ def test_get_parameter_with_version_and_labels():
|
|||||||
response["Parameter"]["Name"].should.equal("test-1")
|
response["Parameter"]["Name"].should.equal("test-1")
|
||||||
response["Parameter"]["Value"].should.equal("value")
|
response["Parameter"]["Value"].should.equal("value")
|
||||||
response["Parameter"]["Type"].should.equal("String")
|
response["Parameter"]["Type"].should.equal("String")
|
||||||
|
response["Parameter"]["DataType"].should.equal("text")
|
||||||
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
||||||
response["Parameter"]["ARN"].should.equal(
|
response["Parameter"]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/test-1".format(ACCOUNT_ID)
|
"arn:aws:ssm:us-east-1:{}:parameter/test-1".format(ACCOUNT_ID)
|
||||||
@ -442,6 +470,7 @@ def test_get_parameter_with_version_and_labels():
|
|||||||
response["Parameter"]["Name"].should.equal("test-2")
|
response["Parameter"]["Name"].should.equal("test-2")
|
||||||
response["Parameter"]["Value"].should.equal("value")
|
response["Parameter"]["Value"].should.equal("value")
|
||||||
response["Parameter"]["Type"].should.equal("String")
|
response["Parameter"]["Type"].should.equal("String")
|
||||||
|
response["Parameter"]["DataType"].should.equal("text")
|
||||||
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
||||||
response["Parameter"]["ARN"].should.equal(
|
response["Parameter"]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
|
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
|
||||||
@ -451,6 +480,7 @@ def test_get_parameter_with_version_and_labels():
|
|||||||
response["Parameter"]["Name"].should.equal("test-2")
|
response["Parameter"]["Name"].should.equal("test-2")
|
||||||
response["Parameter"]["Value"].should.equal("value")
|
response["Parameter"]["Value"].should.equal("value")
|
||||||
response["Parameter"]["Type"].should.equal("String")
|
response["Parameter"]["Type"].should.equal("String")
|
||||||
|
response["Parameter"]["DataType"].should.equal("text")
|
||||||
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
|
||||||
response["Parameter"]["ARN"].should.equal(
|
response["Parameter"]["ARN"].should.equal(
|
||||||
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
|
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
|
||||||
@ -532,6 +562,7 @@ def test_describe_parameters():
|
|||||||
parameters.should.have.length_of(1)
|
parameters.should.have.length_of(1)
|
||||||
parameters[0]["Name"].should.equal("test")
|
parameters[0]["Name"].should.equal("test")
|
||||||
parameters[0]["Type"].should.equal("String")
|
parameters[0]["Type"].should.equal("String")
|
||||||
|
parameters[0]["DataType"].should.equal("text")
|
||||||
parameters[0]["AllowedPattern"].should.equal(r".*")
|
parameters[0]["AllowedPattern"].should.equal(r".*")
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user