Repository: getmoto/moto
Pull request #8348 (2024-11-29 15:23:43)

OpenSearch: richer output

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/8348?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 94.58%. Comparing base [(`10bdd08`)](https://app.codecov.io/gh/getmoto/moto/commit/10bdd0837c8dfef21f22118521cf687119168e99?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`d4e4643`)](https://app.codecov.io/gh/getmoto/moto/commit/d4e4643bf3269abd52fbbd9355c00a268a208941?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).
> Report is 23 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #8348      +/-   ##
==========================================
+ Coverage   94.57%   94.58%   +0.01%     
==========================================
  Files        1159     1159              
  Lines      100936   101129     +193     
==========================================
+ Hits        95458    95655     +197     
+ Misses       5478     5474       -4     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/8348/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/8348/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `28.90% <41.66%> (+<0.01%)` | :arrow_up: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/8348/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `94.55% <100.00%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/8348?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/moto/opensearch/models.py b/moto/opensearch/models.py
index 5032e0adc..31c91821d 100644
--- a/moto/opensearch/models.py
+++ b/moto/opensearch/models.py
@@ -1,7 +1,9 @@
+import datetime
 from typing import Any, Dict, List, Optional
 
 from moto.core.base_backend import BackendDict, BaseBackend
 from moto.core.common_models import BaseModel
+from moto.core.utils import unix_time
 from moto.utilities.tagging_service import TaggingService
 from moto.utilities.utils import get_partition
 
@@ -42,6 +44,25 @@ default_advanced_options = {
 }
 
 
+class EngineVersion(BaseModel):
+    def __init__(self, options: str, create_time: datetime.datetime) -> None:
+        self.options = options or "OpenSearch_2.5"
+        self.create_time = unix_time(create_time)
+        self.update_time = self.create_time
+
+    def to_dict(self) -> Dict[str, Any]:
+        return {
+            "Options": self.options,
+            "Status": {
+                "CreationDate": self.create_time,
+                "PendingDeletion": False,
+                "State": "Active",
+                "UpdateDate": self.update_time,
+                "UpdateVersion": 28,
+            },
+        }
+
+
 class OpenSearchDomain(BaseModel):
     def __init__(
         self,
@@ -70,7 +91,7 @@ class OpenSearchDomain(BaseModel):
         self.arn = (
             f"arn:{get_partition(region)}:es:{region}:{account_id}:domain/{domain_name}"
         )
-        self.engine_version = engine_version or "OpenSearch 2.5"
+        self.engine_version = EngineVersion(engine_version, datetime.datetime.now())
         self.cluster_config = cluster_config or {}
         self.ebs_options = ebs_options or {"EBSEnabled": False}
         self.access_policies = access_policies or ""
@@ -120,7 +141,7 @@ class OpenSearchDomain(BaseModel):
         return {
             "Endpoint": self.endpoint,
             "Endpoints": self.endpoints,
-            "EngineVersion": self.engine_version,
+            "EngineVersion": self.engine_version.to_dict(),
             "ClusterConfig": self.cluster_config,
             "EBSOptions": self.ebs_options,
             "AccessPolicies": self.access_policies,
@@ -207,6 +228,7 @@ class OpenSearchDomain(BaseModel):
         self.software_update_options = (
             software_update_options or self.software_update_options
         )
+        self.engine_version.update_time = unix_time(datetime.datetime.now())
 
 
 class OpenSearchServiceBackend(BaseBackend):
@@ -335,7 +357,7 @@ class OpenSearchServiceBackend(BaseBackend):
         domains = []
         for domain in self.domains.values():
             if engine_type:
-                if engine_type in domain.engine_version:
+                if engine_type in domain.engine_version.options:
                     domains.append(
                         {
                             "DomainName": domain.domain_name,
@@ -348,7 +370,7 @@ class OpenSearchServiceBackend(BaseBackend):
                 domains.append(
                     {
                         "DomainName": domain.domain_name,
-                        "EngineType": domain.engine_version.split("_")[0],
+                        "EngineType": domain.engine_version.options.split("_")[0],
                     }
                 )
         return domains
diff --git a/moto/s3/responses.py b/moto/s3/responses.py
index d0c82428a..c4427212c 100644
--- a/moto/s3/responses.py
+++ b/moto/s3/responses.py
@@ -124,7 +124,7 @@ ACTION_MAP = {
         },
     },
     "KEY": {
-        "HEAD": {"DEFAULT": "HeadObject"},
+        "HEAD": {"DEFAULT": "GetObject"},
         "GET": {
             "uploadId": "ListMultipartUploadParts",
             "acl": "GetObjectAcl",


Test patch:
diff --git a/tests/test_opensearch/test_opensearch.py b/tests/test_opensearch/test_opensearch.py
index 7c92475fb..1ce66fef1 100644
--- a/tests/test_opensearch/test_opensearch.py
+++ b/tests/test_opensearch/test_opensearch.py
@@ -1,8 +1,9 @@
 import boto3
 import pytest
 from botocore.exceptions import ClientError
+from freezegun import freeze_time
 
-from moto import mock_aws
+from moto import mock_aws, settings
 
 # See our Development Tips on writing tests for hints on how to write good tests:
 # http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
@@ -47,7 +48,7 @@ def test_create_domain_with_some_options():
         EngineVersion="OpenSearch_1.1",
     )["DomainStatus"]
     assert status["Created"]
-    assert status["EngineVersion"] == "OpenSearch_1.1"
+    assert status["EngineVersion"]["Options"] == "OpenSearch_1.1"
     assert status["DomainEndpointOptions"] == {
         "EnforceHTTPS": True,
         "TLSSecurityPolicy": "Policy-Min-TLS-1-0-2019-07",
@@ -89,14 +90,27 @@ def test_describe_unknown_domain():
 
 
 @mock_aws
+@freeze_time("2015-01-01 12:00:00")
 def test_describe_domain():
+    # Setup
     client = boto3.client("opensearch", region_name="eu-west-1")
     client.create_domain(DomainName="testdn")
 
+    # Execute
     status = client.describe_domain(DomainName="testdn")["DomainStatus"]
+    ev_status = status["EngineVersion"]["Status"]
+
+    # Verify
     assert "DomainId" in status
     assert "DomainName" in status
     assert status["DomainName"] == "testdn"
+    assert status["EngineVersion"]["Options"] == "OpenSearch_2.5"
+    assert ev_status["State"] == "Active"
+    assert ev_status["PendingDeletion"] is False
+
+    if not settings.TEST_SERVER_MODE:
+        assert ev_status["CreationDate"] == 1420113600.0
+        assert ev_status["UpdateDate"] == 1420113600.0
 
 
 @mock_aws