diff --git a/api/swagger.yml b/api/swagger.yml index e6eb6e905ee..0c59b35be6f 100644 --- a/api/swagger.yml +++ b/api/swagger.yml @@ -1369,6 +1369,10 @@ components: content_type: type: string description: Object media type + mtime: + type: integer + format: int64 + description: Unix Epoch in seconds. May be ignored by server. force: type: boolean default: false diff --git a/clients/java-legacy/api/openapi.yaml b/clients/java-legacy/api/openapi.yaml index f1b26bc88b5..50741121d4a 100644 --- a/clients/java-legacy/api/openapi.yaml +++ b/clients/java-legacy/api/openapi.yaml @@ -9209,6 +9209,7 @@ components: content_type: content_type checksum: checksum force: false + mtime: 6 staging: physical_address: physical_address presigned_url: presigned_url @@ -9230,6 +9231,10 @@ components: content_type: description: Object media type type: string + mtime: + description: Unix Epoch in seconds. May be ignored by server. + format: int64 + type: integer force: default: false type: boolean diff --git a/clients/java-legacy/docs/StagingMetadata.md b/clients/java-legacy/docs/StagingMetadata.md index 4228387befd..41b274d8b61 100644 --- a/clients/java-legacy/docs/StagingMetadata.md +++ b/clients/java-legacy/docs/StagingMetadata.md @@ -13,6 +13,7 @@ Name | Type | Description | Notes **sizeBytes** | **Long** | | **userMetadata** | **Map<String, String>** | | [optional] **contentType** | **String** | Object media type | [optional] +**mtime** | **Long** | Unix Epoch in seconds. May be ignored by server. | [optional] **force** | **Boolean** | | [optional] diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StagingMetadata.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StagingMetadata.java index c8fedda6a6e..b2c5674964d 100644 --- a/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StagingMetadata.java +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StagingMetadata.java @@ -54,6 +54,10 @@ public class StagingMetadata { @SerializedName(SERIALIZED_NAME_CONTENT_TYPE) private String contentType; + public static final String SERIALIZED_NAME_MTIME = "mtime"; + @SerializedName(SERIALIZED_NAME_MTIME) + private Long mtime; + public static final String SERIALIZED_NAME_FORCE = "force"; @SerializedName(SERIALIZED_NAME_FORCE) private Boolean force = false; @@ -182,6 +186,29 @@ public void setContentType(String contentType) { } + public StagingMetadata mtime(Long mtime) { + + this.mtime = mtime; + return this; + } + + /** + * Unix Epoch in seconds. May be ignored by server. + * @return mtime + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "Unix Epoch in seconds. May be ignored by server.") + + public Long getMtime() { + return mtime; + } + + + public void setMtime(Long mtime) { + this.mtime = mtime; + } + + public StagingMetadata force(Boolean force) { this.force = force; @@ -219,12 +246,13 @@ public boolean equals(Object o) { Objects.equals(this.sizeBytes, stagingMetadata.sizeBytes) && Objects.equals(this.userMetadata, stagingMetadata.userMetadata) && Objects.equals(this.contentType, stagingMetadata.contentType) && + Objects.equals(this.mtime, stagingMetadata.mtime) && Objects.equals(this.force, stagingMetadata.force); } @Override public int hashCode() { - return Objects.hash(staging, checksum, sizeBytes, userMetadata, contentType, force); + return Objects.hash(staging, checksum, sizeBytes, userMetadata, contentType, mtime, force); } @Override @@ -236,6 +264,7 @@ public String toString() { sb.append(" sizeBytes: ").append(toIndentedString(sizeBytes)).append("\n"); sb.append(" userMetadata: ").append(toIndentedString(userMetadata)).append("\n"); sb.append(" contentType: ").append(toIndentedString(contentType)).append("\n"); + sb.append(" mtime: ").append(toIndentedString(mtime)).append("\n"); sb.append(" force: ").append(toIndentedString(force)).append("\n"); sb.append("}"); return sb.toString(); diff --git a/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/StagingMetadataTest.java b/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/StagingMetadataTest.java index c6f0d0e5b17..8d25758fd0e 100644 --- a/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/StagingMetadataTest.java +++ b/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/StagingMetadataTest.java @@ -84,6 +84,14 @@ public void contentTypeTest() { // TODO: test contentType } + /** + * Test the property 'mtime' + */ + @Test + public void mtimeTest() { + // TODO: test mtime + } + /** * Test the property 'force' */ diff --git a/clients/java/api/openapi.yaml b/clients/java/api/openapi.yaml index 90b4e5a569d..0b1700b5e61 100644 --- a/clients/java/api/openapi.yaml +++ b/clients/java/api/openapi.yaml @@ -9183,6 +9183,7 @@ components: content_type: content_type checksum: checksum force: false + mtime: 6 staging: physical_address: physical_address presigned_url: presigned_url @@ -9204,6 +9205,10 @@ components: content_type: description: Object media type type: string + mtime: + description: Unix Epoch in seconds. May be ignored by server. + format: int64 + type: integer force: default: false type: boolean diff --git a/clients/java/docs/StagingMetadata.md b/clients/java/docs/StagingMetadata.md index f80987757bc..523b37d96d7 100644 --- a/clients/java/docs/StagingMetadata.md +++ b/clients/java/docs/StagingMetadata.md @@ -13,6 +13,7 @@ information about uploaded object |**sizeBytes** | **Long** | | | |**userMetadata** | **Map<String, String>** | | [optional] | |**contentType** | **String** | Object media type | [optional] | +|**mtime** | **Long** | Unix Epoch in seconds. May be ignored by server. | [optional] | |**force** | **Boolean** | | [optional] | diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/model/StagingMetadata.java b/clients/java/src/main/java/io/lakefs/clients/sdk/model/StagingMetadata.java index 0e6ad6001c4..3129c314333 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/model/StagingMetadata.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/model/StagingMetadata.java @@ -75,6 +75,10 @@ public class StagingMetadata { @SerializedName(SERIALIZED_NAME_CONTENT_TYPE) private String contentType; + public static final String SERIALIZED_NAME_MTIME = "mtime"; + @SerializedName(SERIALIZED_NAME_MTIME) + private Long mtime; + public static final String SERIALIZED_NAME_FORCE = "force"; @SerializedName(SERIALIZED_NAME_FORCE) private Boolean force = false; @@ -195,6 +199,27 @@ public void setContentType(String contentType) { } + public StagingMetadata mtime(Long mtime) { + + this.mtime = mtime; + return this; + } + + /** + * Unix Epoch in seconds. May be ignored by server. + * @return mtime + **/ + @javax.annotation.Nullable + public Long getMtime() { + return mtime; + } + + + public void setMtime(Long mtime) { + this.mtime = mtime; + } + + public StagingMetadata force(Boolean force) { this.force = force; @@ -275,13 +300,14 @@ public boolean equals(Object o) { Objects.equals(this.sizeBytes, stagingMetadata.sizeBytes) && Objects.equals(this.userMetadata, stagingMetadata.userMetadata) && Objects.equals(this.contentType, stagingMetadata.contentType) && + Objects.equals(this.mtime, stagingMetadata.mtime) && Objects.equals(this.force, stagingMetadata.force)&& Objects.equals(this.additionalProperties, stagingMetadata.additionalProperties); } @Override public int hashCode() { - return Objects.hash(staging, checksum, sizeBytes, userMetadata, contentType, force, additionalProperties); + return Objects.hash(staging, checksum, sizeBytes, userMetadata, contentType, mtime, force, additionalProperties); } @Override @@ -293,6 +319,7 @@ public String toString() { sb.append(" sizeBytes: ").append(toIndentedString(sizeBytes)).append("\n"); sb.append(" userMetadata: ").append(toIndentedString(userMetadata)).append("\n"); sb.append(" contentType: ").append(toIndentedString(contentType)).append("\n"); + sb.append(" mtime: ").append(toIndentedString(mtime)).append("\n"); sb.append(" force: ").append(toIndentedString(force)).append("\n"); sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append("}"); @@ -322,6 +349,7 @@ private String toIndentedString(Object o) { openapiFields.add("size_bytes"); openapiFields.add("user_metadata"); openapiFields.add("content_type"); + openapiFields.add("mtime"); openapiFields.add("force"); // a set of required properties/fields (JSON key names) diff --git a/clients/java/src/test/java/io/lakefs/clients/sdk/model/StagingMetadataTest.java b/clients/java/src/test/java/io/lakefs/clients/sdk/model/StagingMetadataTest.java index d11a7d6b96e..c748a47f867 100644 --- a/clients/java/src/test/java/io/lakefs/clients/sdk/model/StagingMetadataTest.java +++ b/clients/java/src/test/java/io/lakefs/clients/sdk/model/StagingMetadataTest.java @@ -80,6 +80,14 @@ public void contentTypeTest() { // TODO: test contentType } + /** + * Test the property 'mtime' + */ + @Test + public void mtimeTest() { + // TODO: test mtime + } + /** * Test the property 'force' */ diff --git a/clients/python-legacy/docs/StagingApi.md b/clients/python-legacy/docs/StagingApi.md index 4049f989555..476f32be4d5 100644 --- a/clients/python-legacy/docs/StagingApi.md +++ b/clients/python-legacy/docs/StagingApi.md @@ -214,6 +214,7 @@ with lakefs_client.ApiClient(configuration) as api_client: "key": "key_example", }, content_type="content_type_example", + mtime=1, force=False, ) # StagingMetadata | if_none_match = "*" # str | Set to \"*\" to atomically allow the upload only if the key has no object yet. Other values are not supported. (optional) diff --git a/clients/python-legacy/docs/StagingMetadata.md b/clients/python-legacy/docs/StagingMetadata.md index 21cca48909a..6b9c35c11c5 100644 --- a/clients/python-legacy/docs/StagingMetadata.md +++ b/clients/python-legacy/docs/StagingMetadata.md @@ -10,6 +10,7 @@ Name | Type | Description | Notes **size_bytes** | **int** | | **user_metadata** | **{str: (str,)}** | | [optional] **content_type** | **str** | Object media type | [optional] +**mtime** | **int** | Unix Epoch in seconds. May be ignored by server. | [optional] **force** | **bool** | | [optional] if omitted the server will use the default value of False **any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] diff --git a/clients/python-legacy/lakefs_client/model/staging_metadata.py b/clients/python-legacy/lakefs_client/model/staging_metadata.py index 4e6414fc15c..512b3cfe7c3 100644 --- a/clients/python-legacy/lakefs_client/model/staging_metadata.py +++ b/clients/python-legacy/lakefs_client/model/staging_metadata.py @@ -93,6 +93,7 @@ def openapi_types(): 'size_bytes': (int,), # noqa: E501 'user_metadata': ({str: (str,)},), # noqa: E501 'content_type': (str,), # noqa: E501 + 'mtime': (int,), # noqa: E501 'force': (bool,), # noqa: E501 } @@ -107,6 +108,7 @@ def discriminator(): 'size_bytes': 'size_bytes', # noqa: E501 'user_metadata': 'user_metadata', # noqa: E501 'content_type': 'content_type', # noqa: E501 + 'mtime': 'mtime', # noqa: E501 'force': 'force', # noqa: E501 } @@ -158,6 +160,7 @@ def _from_openapi_data(cls, staging, checksum, size_bytes, *args, **kwargs): # _visited_composed_classes = (Animal,) user_metadata ({str: (str,)}): [optional] # noqa: E501 content_type (str): Object media type. [optional] # noqa: E501 + mtime (int): Unix Epoch in seconds. May be ignored by server.. [optional] # noqa: E501 force (bool): [optional] if omitted the server will use the default value of False # noqa: E501 """ @@ -250,6 +253,7 @@ def __init__(self, staging, checksum, size_bytes, *args, **kwargs): # noqa: E50 _visited_composed_classes = (Animal,) user_metadata ({str: (str,)}): [optional] # noqa: E501 content_type (str): Object media type. [optional] # noqa: E501 + mtime (int): Unix Epoch in seconds. May be ignored by server.. [optional] # noqa: E501 force (bool): [optional] if omitted the server will use the default value of False # noqa: E501 """ diff --git a/clients/python/docs/StagingMetadata.md b/clients/python/docs/StagingMetadata.md index 7e52333ff9e..74c9dc60f4d 100644 --- a/clients/python/docs/StagingMetadata.md +++ b/clients/python/docs/StagingMetadata.md @@ -11,6 +11,7 @@ Name | Type | Description | Notes **size_bytes** | **int** | | **user_metadata** | **Dict[str, str]** | | [optional] **content_type** | **str** | Object media type | [optional] +**mtime** | **int** | Unix Epoch in seconds. May be ignored by server. | [optional] **force** | **bool** | | [optional] [default to False] ## Example diff --git a/clients/python/lakefs_sdk/models/staging_metadata.py b/clients/python/lakefs_sdk/models/staging_metadata.py index 26a0fe1f3d9..c3e548f7964 100644 --- a/clients/python/lakefs_sdk/models/staging_metadata.py +++ b/clients/python/lakefs_sdk/models/staging_metadata.py @@ -35,8 +35,9 @@ class StagingMetadata(BaseModel): size_bytes: StrictInt = Field(...) user_metadata: Optional[Dict[str, StrictStr]] = None content_type: Optional[StrictStr] = Field(None, description="Object media type") + mtime: Optional[StrictInt] = Field(None, description="Unix Epoch in seconds. May be ignored by server.") force: Optional[StrictBool] = False - __properties = ["staging", "checksum", "size_bytes", "user_metadata", "content_type", "force"] + __properties = ["staging", "checksum", "size_bytes", "user_metadata", "content_type", "mtime", "force"] class Config: """Pydantic configuration""" @@ -82,6 +83,7 @@ def from_dict(cls, obj: dict) -> StagingMetadata: "size_bytes": obj.get("size_bytes"), "user_metadata": obj.get("user_metadata"), "content_type": obj.get("content_type"), + "mtime": obj.get("mtime"), "force": obj.get("force") if obj.get("force") is not None else False }) return _obj diff --git a/clients/python/test/test_staging_metadata.py b/clients/python/test/test_staging_metadata.py index 3623b7c8884..74b0a71c118 100644 --- a/clients/python/test/test_staging_metadata.py +++ b/clients/python/test/test_staging_metadata.py @@ -49,6 +49,7 @@ def make_instance(self, include_optional): 'key' : '' }, content_type = '', + mtime = 56, force = True ) else : diff --git a/clients/rust/docs/StagingMetadata.md b/clients/rust/docs/StagingMetadata.md index 5749a9a5e04..afbdce0b7a3 100644 --- a/clients/rust/docs/StagingMetadata.md +++ b/clients/rust/docs/StagingMetadata.md @@ -9,6 +9,7 @@ Name | Type | Description | Notes **size_bytes** | **i64** | | **user_metadata** | Option<**std::collections::HashMap**> | | [optional] **content_type** | Option<**String**> | Object media type | [optional] +**mtime** | Option<**i64**> | Unix Epoch in seconds. May be ignored by server. | [optional] **force** | Option<**bool**> | | [optional][default to false] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/rust/src/models/staging_metadata.rs b/clients/rust/src/models/staging_metadata.rs index 76f58e74c67..c9f640df651 100644 --- a/clients/rust/src/models/staging_metadata.rs +++ b/clients/rust/src/models/staging_metadata.rs @@ -25,6 +25,9 @@ pub struct StagingMetadata { /// Object media type #[serde(rename = "content_type", skip_serializing_if = "Option::is_none")] pub content_type: Option, + /// Unix Epoch in seconds. May be ignored by server. + #[serde(rename = "mtime", skip_serializing_if = "Option::is_none")] + pub mtime: Option, #[serde(rename = "force", skip_serializing_if = "Option::is_none")] pub force: Option, } @@ -38,6 +41,7 @@ impl StagingMetadata { size_bytes, user_metadata: None, content_type: None, + mtime: None, force: None, } } diff --git a/docs/assets/js/swagger.yml b/docs/assets/js/swagger.yml index e6eb6e905ee..0c59b35be6f 100644 --- a/docs/assets/js/swagger.yml +++ b/docs/assets/js/swagger.yml @@ -1369,6 +1369,10 @@ components: content_type: type: string description: Object media type + mtime: + type: integer + format: int64 + description: Unix Epoch in seconds. May be ignored by server. force: type: boolean default: false diff --git a/pkg/api/controller.go b/pkg/api/controller.go index 1623dc74cfd..73946ff6688 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -769,6 +769,9 @@ func (c *Controller) LinkPhysicalAddress(w http.ResponseWriter, r *http.Request, } writeTime := time.Now() + if mtime := body.Mtime; mtime != nil { + writeTime = time.Unix(*mtime, 0) + } fullPhysicalAddress := swag.StringValue(body.Staging.PhysicalAddress) physicalAddress, addressType := normalizePhysicalAddress(repo.StorageNamespace, fullPhysicalAddress)