Repository: getmoto/moto

Issue:
list secretsManager returns "VersionIdsToStages" field but the aws apis call it "SecretVersionsToStages"
The response to list_secrets from aws secretsmanager, has a field in the secret_list_entry that is misnamed. I discovered this when making a call to list_secrets via the latest localstack/localstack docker container 0.12.0 (which includes this library).

"VersionIdsToStages" should instead be "SecretVersionsToStages"

I think all that needs changing is the response model here:
https://github.com/spulec/moto/blob/14980371d796ef849b1ea401ce2c028911b537d1/moto/secretsmanager/models.py#L138

You can see the "SecretVersionsToStages" field in the "ResponseSyntax" example, in the aws api docs here:
https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_ListSecrets.html

And in the java sdk here:
https://github.com/aws/aws-sdk-java/blob/83f1a7c1bef7bab8f809f5123275848678fb807b/aws-java-sdk-secretsmanager/src/main/java/com/amazonaws/services/secretsmanager/model/transform/SecretListEntryJsonUnmarshaller.java#L101

localstack is including moto.secretsmanager here:
https://github.com/localstack/localstack/blob/d43a58d563a5a912de64d4e9c8bcac28a96d3857/localstack/services/secretsmanager/secretsmanager_starter.py#L2


Discussion:
Thanks for raising this @DuaneKrause - marking it as an bug

Resolving patch:
diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py
--- a/moto/secretsmanager/models.py
+++ b/moto/secretsmanager/models.py
@@ -136,6 +136,7 @@ def to_dict(self):
             "DeletedDate": self.deleted_date,
             "Tags": self.tags,
             "VersionIdsToStages": version_id_to_stages,
+            "SecretVersionsToStages": version_id_to_stages,
         }
 
     def _form_version_ids_to_stages(self):


Test patch:
diff --git a/tests/test_secretsmanager/test_list_secrets.py b/tests/test_secretsmanager/test_list_secrets.py
--- a/tests/test_secretsmanager/test_list_secrets.py
+++ b/tests/test_secretsmanager/test_list_secrets.py
@@ -43,9 +43,11 @@ def test_list_secrets():
 
     assert secrets["SecretList"][0]["ARN"] is not None
     assert secrets["SecretList"][0]["Name"] == "test-secret"
+    assert secrets["SecretList"][0]["SecretVersionsToStages"] is not None
     assert secrets["SecretList"][1]["ARN"] is not None
     assert secrets["SecretList"][1]["Name"] == "test-secret-2"
     assert secrets["SecretList"][1]["Tags"] == [{"Key": "a", "Value": "1"}]
+    assert secrets["SecretList"][1]["SecretVersionsToStages"] is not None
 
 
 @mock_secretsmanager
diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py
--- a/tests/test_secretsmanager/test_secretsmanager.py
+++ b/tests/test_secretsmanager/test_secretsmanager.py
@@ -963,3 +963,32 @@ def test_tag_resource():
         "Secrets Manager can't find the specified secret.",
         cm.exception.response["Error"]["Message"],
     )
+
+
+@mock_secretsmanager
+def test_secret_versions_to_stages_attribute_discrepancy():
+    client = boto3.client("secretsmanager", region_name="us-west-2")
+
+    resp = client.create_secret(Name=DEFAULT_SECRET_NAME, SecretString="foosecret")
+    previous_version_id = resp["VersionId"]
+
+    resp = client.put_secret_value(
+        SecretId=DEFAULT_SECRET_NAME,
+        SecretString="dupe_secret",
+        VersionStages=["AWSCURRENT"],
+    )
+    current_version_id = resp["VersionId"]
+
+    secret = client.describe_secret(SecretId=DEFAULT_SECRET_NAME)
+    describe_vtos = secret["VersionIdsToStages"]
+    assert describe_vtos[current_version_id] == ["AWSCURRENT"]
+    assert describe_vtos[previous_version_id] == ["AWSPREVIOUS"]
+
+    secret = client.list_secrets(
+        Filters=[{"Key": "name", "Values": [DEFAULT_SECRET_NAME]}]
+    ).get("SecretList")[0]
+    list_vtos = secret["SecretVersionsToStages"]
+    assert list_vtos[current_version_id] == ["AWSCURRENT"]
+    assert list_vtos[previous_version_id] == ["AWSPREVIOUS"]
+
+    assert describe_vtos == list_vtos