Repository: getmoto/moto

Issue:
ssm.get_parameter response contains no field DataType
The ssm [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter) function returns a field called `DataType`.  However `mock_ssm()` does not.

 ```python
import os

import boto3
import pytest
from moto import mock_ssm

@pytest.fixture
def aws_credentials():
    os.environ["AWS_ACCESS_KEY_ID"] = "testing"
    os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
    os.environ["AWS_SECURITY_TOKEN"] = "testing"
    os.environ["AWS_SESSION_TOKEN"] = "testing"


@pytest.fixture
def ssm_mock(aws_credentials):
    with mock_ssm():
        client = boto3.client("ssm", region_name="us-west-2")
        client.put_parameter(
            Name='parameter-name',
            Description='parameter-description',
            Value='parameter-value',
            Type='String',
            DataType='string'
        )
        yield


def test_get_parameter(ssm_mock):
    ssm = boto3.client("ssm", region_name="us-west-2")
    actual = ssm.get_parameter(Name="parameter-name", WithDecryption=False)

    assert "DataType" in actual["Parameter"]
```

Results

```python
>       assert "DataType" in actual["Parameter"]
E       AssertionError: assert 'DataType' in {'ARN': 'arn:aws:ssm:us-west-2:123456789012:parameter/parameter-name', 'LastModifiedDate': datetime.datetime(2021, 8, 23, 20, 5, 10, 520000, tzinfo=tzlocal()), 'Name': 'parameter-name', 'Type': 'String', ...}
```



Discussion:
Thanks for raising this @bruce-szalwinski. Doesn't look like we even persist this parameter. Raising it as an enhancement to persist and return `DataType`.
Is this available to be worked on? I would like to contribute @bblommers 
I'm not aware of anyone else working on this @jlopezscala , so if you want to pick it up, a PR would be very welcome!
@jlopezscala if you don't, I will :).
I'll do my best! 

Resolving patch:
diff --git a/moto/ssm/models.py b/moto/ssm/models.py
--- a/moto/ssm/models.py
+++ b/moto/ssm/models.py
@@ -55,6 +55,7 @@ def __init__(
         keyid,
         last_modified_date,
         version,
+        data_type,
         tags=None,
     ):
         self.name = name
@@ -64,6 +65,7 @@ def __init__(
         self.keyid = keyid
         self.last_modified_date = last_modified_date
         self.version = version
+        self.data_type = data_type
         self.tags = tags or []
         self.labels = []
 
@@ -93,6 +95,7 @@ def response_object(self, decrypt=False, region=None):
             "Value": self.decrypt(self.value) if decrypt else self.value,
             "Version": self.version,
             "LastModifiedDate": round(self.last_modified_date, 3),
+            "DataType": self.data_type,
         }
 
         if region:
@@ -618,6 +621,14 @@ def _document_filter_match(filters, ssm_doc):
     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):
     def __init__(self, region_name=None):
         super(SimpleSystemManagerBackend, self).__init__()
@@ -1480,7 +1491,16 @@ def _check_for_parameter_version_limit_exception(self, name):
             )
 
     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:
             raise ValidationException(
@@ -1504,6 +1524,15 @@ def put_parameter(
                     "formed as a mix of letters, numbers and the following 3 symbols .-_"
                 )
             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]
         if len(previous_parameter_versions) == 0:
             previous_parameter = None
@@ -1522,15 +1551,16 @@ def put_parameter(
         last_modified_date = time.time()
         self._parameters[name].append(
             Parameter(
-                name,
-                value,
-                type,
-                description,
-                allowed_pattern,
-                keyid,
-                last_modified_date,
-                version,
-                tags or [],
+                name=name,
+                value=value,
+                type=type,
+                description=description,
+                allowed_pattern=allowed_pattern,
+                keyid=keyid,
+                last_modified_date=last_modified_date,
+                version=version,
+                tags=tags or [],
+                data_type=data_type,
             )
         )
 
diff --git a/moto/ssm/responses.py b/moto/ssm/responses.py
--- a/moto/ssm/responses.py
+++ b/moto/ssm/responses.py
@@ -277,9 +277,18 @@ def put_parameter(self):
         keyid = self._get_param("KeyId")
         overwrite = self._get_param("Overwrite", False)
         tags = self._get_param("Tags", [])
+        data_type = self._get_param("DataType", "text")
 
         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:


Test patch:
diff --git a/tests/test_ssm/test_ssm_boto3.py b/tests/test_ssm/test_ssm_boto3.py
--- a/tests/test_ssm/test_ssm_boto3.py
+++ b/tests/test_ssm/test_ssm_boto3.py
@@ -232,9 +232,8 @@ def test_get_parameters_by_path():
 @mock_ssm
 def test_put_parameter(name):
     client = boto3.client("ssm", region_name="us-east-1")
-
     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)
@@ -246,6 +245,7 @@ def test_put_parameter(name):
     response["Parameters"][0]["Value"].should.equal("value")
     response["Parameters"][0]["Type"].should.equal("String")
     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]["ARN"].should.equal(
         "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]["Type"].should.equal("String")
     response["Parameters"][0]["Version"].should.equal(1)
+    response["Parameters"][0]["DataType"].should.equal("text")
     response["Parameters"][0]["LastModifiedDate"].should.equal(
         initial_modification_date
     )
     response["Parameters"][0]["ARN"].should.equal(
         "arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
     )
-
+    new_data_type = "aws:ec2:image"
     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)
@@ -292,6 +298,8 @@ def test_put_parameter(name):
     response["Parameters"][0]["Value"].should.equal("value 3")
     response["Parameters"][0]["Type"].should.equal("String")
     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(
         initial_modification_date
     )
@@ -394,12 +402,30 @@ def test_put_parameter_china():
     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
 def test_get_parameter():
     client = boto3.client("ssm", region_name="us-east-1")
 
     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)
@@ -407,6 +433,7 @@ def test_get_parameter():
     response["Parameter"]["Name"].should.equal("test")
     response["Parameter"]["Value"].should.equal("value")
     response["Parameter"]["Type"].should.equal("String")
+    response["Parameter"]["DataType"].should.equal("text")
     response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
     response["Parameter"]["ARN"].should.equal(
         "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.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(
-        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(
@@ -433,6 +460,7 @@ def test_get_parameter_with_version_and_labels():
     response["Parameter"]["Name"].should.equal("test-1")
     response["Parameter"]["Value"].should.equal("value")
     response["Parameter"]["Type"].should.equal("String")
+    response["Parameter"]["DataType"].should.equal("text")
     response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
     response["Parameter"]["ARN"].should.equal(
         "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"]["Value"].should.equal("value")
     response["Parameter"]["Type"].should.equal("String")
+    response["Parameter"]["DataType"].should.equal("text")
     response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
     response["Parameter"]["ARN"].should.equal(
         "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"]["Value"].should.equal("value")
     response["Parameter"]["Type"].should.equal("String")
+    response["Parameter"]["DataType"].should.equal("text")
     response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
     response["Parameter"]["ARN"].should.equal(
         "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[0]["Name"].should.equal("test")
     parameters[0]["Type"].should.equal("String")
+    parameters[0]["DataType"].should.equal("text")
     parameters[0]["AllowedPattern"].should.equal(r".*")