From 1420d16a4f8295059bebe3b1524a72c3315b93f5 Mon Sep 17 00:00:00 2001 From: Nathalie Jonathan Date: Fri, 13 Dec 2024 13:48:21 -0800 Subject: [PATCH 1/7] Added ML Model APIs (get, search, update model) to the spec along with the tests Signed-off-by: Nathalie Jonathan --- CHANGELOG.md | 1 + spec/namespaces/ml.yaml | 81 ++++++++++++++++++ spec/schemas/ml._common.yaml | 146 ++++++++++++++++++++++++++++++++ tests/plugins/ml/ml/models.yaml | 31 +++++++ 4 files changed, 259 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6fdd6040..be50b8000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added response schema for `PUT` and `DELETE /_plugins/_transform/{id}` ([#722](https://github.com/opensearch-project/opensearch-api-specification/pull/716)) - Added response schema for `GET /_plugins/_knn/warmup/{index}` ([#717](https://github.com/opensearch-project/opensearch-api-specification/pull/717)) - Added support for multiple test verbs ([#724](https://github.com/opensearch-project/opensearch-api-specification/pull/724)) +- Added ML Model APIs `GET /_plugins/_ml/models/{}`, `POST /_plugins/_ml/models/_search`, and `PUT /_plugins/_ml/models/{}` to the spec along with the tests. ### Removed - Removed unsupported `_common.mapping:SourceField`'s `mode` field and associated `_common.mapping:SourceFieldMode` enum ([#652](https://github.com/opensearch-project/opensearch-api-specification/pull/652)) diff --git a/spec/namespaces/ml.yaml b/spec/namespaces/ml.yaml index 67ec2460a..1148c496e 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -44,6 +44,26 @@ paths: '200': $ref: '#/components/responses/ml.register_model@200' /_plugins/_ml/models/{model_id}: + get: + operationId: ml.get_model.0 + x-operation-group: ml.get_model + description: Retrieves a model. + parameters: + - $ref: '#/components/parameters/ml.get_model::path.model_id' + responses: + '200': + $ref: '#/components/responses/ml.get_model@200' + put: + operationId: ml.update_model.0 + x-operation-group: ml.update_model + description: Updates a model. + parameters: + - $ref: '#/components/parameters/ml.update_model::path.model_id' + requestBody: + $ref: '#/components/requestBodies/ml.update_model' + responses: + '200': + $ref: '#/components/responses/ml.update_model@200' delete: operationId: ml.delete_model.0 x-operation-group: ml.delete_model @@ -102,6 +122,15 @@ paths: responses: '200': $ref: '#/components/responses/ml.search_models@200' + post: + operationId: ml.search_models.0 + x-operation-group: ml.search_models + description: Searches for models. + requestBody: + $ref: '#/components/requestBodies/ml.search_models' + responses: + '200': + $ref: '#/components/responses/ml.search_models@200' /_plugins/_ml/connectors/_create: post: operationId: ml.create_connector.0 @@ -212,6 +241,36 @@ components: required: - query - size + ml.update_model: + content: + application/json: + schema: + type: object + properties: + connector: + type: object + description: The connector to use for the model. + connector_id: + type: string + description: The connector ID. + is_enabled: + type: boolean + description: Whether the model is enabled. + description: + type: string + description: The model description. + model_config: + $ref: '../schemas/ml._common.yaml#/components/schemas/ModelConfig' + name: + type: string + description: The model name. + rate_limiter: + $ref: '../schemas/ml._common.yaml#/components/schemas/RateLimiter' + guardrails: + $ref: '../schemas/ml._common.yaml#/components/schemas/Guardrails' + interface: + type: object + description: The model interface. ml.create_connector: content: application/json: @@ -325,6 +384,16 @@ components: application/json: schema: $ref: '../schemas/_common.yaml#/components/schemas/WriteResponseBase' + ml.get_model@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/Model' + ml.update_model@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/UpdateModelResponse' ml.delete_task@200: content: application/json: @@ -385,6 +454,18 @@ components: required: true schema: type: string + ml.get_model::path.model_id: + name: model_id + in: path + required: true + schema: + type: string + ml.update_model::path.model_id: + name: model_id + in: path + required: true + schema: + type: string ml.deploy_model::path.model_id: name: model_id in: path diff --git a/spec/schemas/ml._common.yaml b/spec/schemas/ml._common.yaml index 1b83fcfce..3f1ac9963 100644 --- a/spec/schemas/ml._common.yaml +++ b/spec/schemas/ml._common.yaml @@ -225,6 +225,152 @@ components: - description - latest_version - name + Model: + type: object + properties: + name: + type: string + description: The model name. + model_group_id: + type: string + description: The model group ID. + algorithm: + type: string + description: The algorithm. + model_version: + type: string + description: The model version. + model_format: + type: string + description: The model format. + enum: + - ONNX + - TORCH_SCRIPT + model_state: + type: string + description: The model state. + enum: + - DEPLOYED + - DEPLOYING + - DEPLOY_FAILED + - PARTIALLY_DEPLOYED + - REGISTERED + - REGISTERING + model_content_size_in_bytes: + type: integer + format: int64 + description: The model content size in bytes. + model_content_hash_value: + type: string + description: The model content hash value. + model_config: + $ref: '#/components/schemas/ModelConfig' + created_time: + type: integer + format: int64 + description: The created time. + last_updated_time: + type: integer + format: int64 + description: The last updated time. + last_registered_time: + type: integer + format: int64 + description: The last registered time. + total_chunks: + type: integer + format: int64 + description: The total chunks. + is_hidden: + type: boolean + description: Whether the model is hidden. + required: + - model_state + RateLimiter: + type: object + properties: + limit: + type: integer + format: int64 + description: The maximum limit. + unit: + type: string + description: The unit of time. + enum: + - DAYS + - HOURS + - MICROSECONDS + - MILLISECONDS + - MINUTES + - NANOSECONDS + - SECONDS + required: + - limit + - unit + Guardrails: + type: object + properties: + type: + type: string + description: The guardrails type. + enum: + - local_regex + - model + input_guardrail: + $ref: '#/components/schemas/GuardrailsInputOutput' + output_guardrail: + $ref: '#/components/schemas/GuardrailsInputOutput' + stop_words: + $ref: '_common.analysis.yaml#/components/schemas/StopWords' + index_name: + $ref: '_common.yaml#/components/schemas/IndexName' + source_fields: + $ref: '_common.yaml#/components/schemas/Fields' + regex: + type: object + description: The regex used for input/output validation. + model_id: + type: string + description: The model ID. + response_filter: + type: string + description: The response filter. + response_validation_regex: + type: string + description: The response validation regex. + GuardrailsInputOutput: + type: object + properties: + model_id: + type: string + description: The model ID. + response_validation_regex: + type: string + description: The response validation regex. + UpdateModelResponse: + type: object + properties: + _index: + $ref: '_common.yaml#/components/schemas/IndexName' + _id: + $ref: '_common.yaml#/components/schemas/Id' + _version: + $ref: '_common.yaml#/components/schemas/VersionNumber' + result: + $ref: '_common.yaml#/components/schemas/Result' + forced_refresh: + type: boolean + description: Whether the model is forced to refresh. + _shards: + $ref: '_common.yaml#/components/schemas/ShardStatistics' + _seq_no: + $ref: '_common.yaml#/components/schemas/SequenceNumber' + _primary_term: + type: integer + format: int64 + description: The primary term. + required: + - _index Task: type: object properties: diff --git a/tests/plugins/ml/ml/models.yaml b/tests/plugins/ml/ml/models.yaml index 92cac3ca3..9d2b539e7 100644 --- a/tests/plugins/ml/ml/models.yaml +++ b/tests/plugins/ml/ml/models.yaml @@ -51,6 +51,37 @@ chapters: hits: hits: - _score: 1 + - synopsis: Search model. + path: /_plugins/_ml/models/_search + method: POST + request: + payload: + query: + match_all: {} + size: 1000 + response: + status: 200 + payload: + hits: + hits: + - _score: 1 + - synopsis: Get model. + path: /_plugins/_ml/models/{model_id} + method: GET + parameters: + model_id: ${get_completed_task.model_id} + response: + status: 200 + - synopsis: Update model. + path: /_plugins/_ml/models/{model_id} + method: PUT + parameters: + model_id: ${get_completed_task.model_id} + request: + payload: + name: updated_name + response: + status: 200 - synopsis: Delete model. path: /_plugins/_ml/models/{model_id} parameters: From 0cc17c248926733d91fdaf0f8b16f6a3e27f8ab1 Mon Sep 17 00:00:00 2001 From: Nathalie Jonathan Date: Mon, 16 Dec 2024 17:45:38 -0800 Subject: [PATCH 2/7] Added ML Model APIs (undeploy, unload), moved test for search model to models/search.yaml, resolved conflicts and updated CHANGELOG Signed-off-by: Nathalie Jonathan --- CHANGELOG.md | 3 +- spec/namespaces/ml.yaml | 80 ++++++++++++++++++- spec/schemas/ml._common.yaml | 15 ++++ tests/plugins/ml/ml/models.yaml | 16 +--- tests/plugins/ml/models/search.yaml | 34 ++++++++ .../ml/models/undeploy_specific_models.yaml | 77 ++++++++++++++++++ tests/plugins/ml/models/unload.yaml | 74 +++++++++++++++++ .../ml/models/unload_specific_models.yaml | 76 ++++++++++++++++++ 8 files changed, 357 insertions(+), 18 deletions(-) create mode 100644 tests/plugins/ml/models/search.yaml create mode 100644 tests/plugins/ml/models/undeploy_specific_models.yaml create mode 100644 tests/plugins/ml/models/unload.yaml create mode 100644 tests/plugins/ml/models/unload_specific_models.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index be50b8000..4df039f3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added response schema for `PUT` and `DELETE /_plugins/_transform/{id}` ([#722](https://github.com/opensearch-project/opensearch-api-specification/pull/716)) - Added response schema for `GET /_plugins/_knn/warmup/{index}` ([#717](https://github.com/opensearch-project/opensearch-api-specification/pull/717)) - Added support for multiple test verbs ([#724](https://github.com/opensearch-project/opensearch-api-specification/pull/724)) -- Added ML Model APIs `GET /_plugins/_ml/models/{}`, `POST /_plugins/_ml/models/_search`, and `PUT /_plugins/_ml/models/{}` to the spec along with the tests. +- Added support for using a certificate and key in tests ([#731](https://github.com/opensearch-project/opensearch-api-specification/pull/731)) +- Added `GET /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/_search`, `PUT /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/{model_id}/_unload`, `POST /_plugins/_ml/models/_unload`, and `POST /_plugins/_ml/models/_undeploy` ([#733](https://github.com/opensearch-project/opensearch-api-specification/pull/733)) ### Removed - Removed unsupported `_common.mapping:SourceField`'s `mode` field and associated `_common.mapping:SourceFieldMode` enum ([#652](https://github.com/opensearch-project/opensearch-api-specification/pull/652)) diff --git a/spec/namespaces/ml.yaml b/spec/namespaces/ml.yaml index 1148c496e..aa576e787 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -93,6 +93,40 @@ paths: responses: '200': $ref: '#/components/responses/ml.undeploy_model@200' + /_plugins/_ml/models/_undeploy: + post: + operationId: ml.undeploy_model.1 + x-operation-group: ml.undeploy_model + description: Undeploys a model. + requestBody: + $ref: '#/components/requestBodies/ml.undeploy_model' + responses: + '200': + $ref: '#/components/responses/ml.undeploy_model@200' + /_plugins/_ml/models/{model_id}/_unload: + post: + operationId: ml.unload_model.0 + x-operation-group: ml.unload_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `undeploy_model` instead. + parameters: + - $ref: '#/components/parameters/ml.unload_model::path.model_id' + responses: + '200': + $ref: '#/components/responses/ml.unload_model@200' + /_plugins/_ml/models/_unload: + post: + operationId: ml.unload_model.1 + x-operation-group: ml.unload_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `undeploy_model` instead. + requestBody: + $ref: '#/components/requestBodies/ml.unload_model' + responses: + '200': + $ref: '#/components/responses/ml.unload_model@200' /_plugins/_ml/tasks/{task_id}: get: operationId: ml.get_task.0 @@ -123,7 +157,7 @@ paths: '200': $ref: '#/components/responses/ml.search_models@200' post: - operationId: ml.search_models.0 + operationId: ml.search_models.1 x-operation-group: ml.search_models description: Searches for models. requestBody: @@ -222,7 +256,6 @@ components: type: string description: The ID of the model group to which to register the model. required: - - model_format - name - version ml.search_models: @@ -271,6 +304,38 @@ components: interface: type: object description: The model interface. + ml.undeploy_model: + content: + application/json: + schema: + type: object + properties: + node_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + model_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + required: + - model_ids + ml.unload_model: + content: + application/json: + schema: + type: object + properties: + node_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + model_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + required: + - model_ids ml.create_connector: content: application/json: @@ -379,6 +444,11 @@ components: application/json: schema: $ref: '../schemas/ml._common.yaml#/components/schemas/UndeployModelResponse' + ml.unload_model@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/UnloadModelResponse' ml.delete_model@200: content: application/json: @@ -478,6 +548,12 @@ components: required: true schema: type: string + ml.unload_model::path.model_id: + name: model_id + in: path + required: true + schema: + type: string ml.delete_task::path.task_id: name: task_id in: path diff --git a/spec/schemas/ml._common.yaml b/spec/schemas/ml._common.yaml index 3f1ac9963..de1b74492 100644 --- a/spec/schemas/ml._common.yaml +++ b/spec/schemas/ml._common.yaml @@ -115,6 +115,7 @@ components: - PARTIALLY_DEPLOYED - REGISTERED - REGISTERING + - UNDEPLOYED model_content_size_in_bytes: type: integer format: int64 @@ -256,6 +257,7 @@ components: - PARTIALLY_DEPLOYED - REGISTERED - REGISTERING + - UNDEPLOYED model_content_size_in_bytes: type: integer format: int64 @@ -424,6 +426,19 @@ components: UndeployModelNodeStats: type: object additionalProperties: true + UnloadModelResponse: + type: object + additionalProperties: + title: nodes + $ref: '#/components/schemas/UnloadModelNode' + UnloadModelNode: + type: object + properties: + stats: + $ref: '#/components/schemas/UnloadModelNodeStats' + UnloadModelNodeStats: + type: object + additionalProperties: true Credential: type: object properties: diff --git a/tests/plugins/ml/ml/models.yaml b/tests/plugins/ml/ml/models.yaml index 9d2b539e7..7258c5d07 100644 --- a/tests/plugins/ml/ml/models.yaml +++ b/tests/plugins/ml/ml/models.yaml @@ -51,20 +51,6 @@ chapters: hits: hits: - _score: 1 - - synopsis: Search model. - path: /_plugins/_ml/models/_search - method: POST - request: - payload: - query: - match_all: {} - size: 1000 - response: - status: 200 - payload: - hits: - hits: - - _score: 1 - synopsis: Get model. path: /_plugins/_ml/models/{model_id} method: GET @@ -79,7 +65,7 @@ chapters: model_id: ${get_completed_task.model_id} request: payload: - name: updated_name + name: updated response: status: 200 - synopsis: Delete model. diff --git a/tests/plugins/ml/models/search.yaml b/tests/plugins/ml/models/search.yaml new file mode 100644 index 000000000..98d79fa5f --- /dev/null +++ b/tests/plugins/ml/models/search.yaml @@ -0,0 +1,34 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the search of models. +distributions: + excluded: + - amazon-managed + - amazon-serverless +version: '>= 2.11' +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +chapters: + - synopsis: Search model. + path: /_plugins/_ml/models/_search + method: POST + request: + payload: + query: + match_all: {} + size: 1000 + response: + status: 200 + payload: + hits: + hits: + - _score: 1 \ No newline at end of file diff --git a/tests/plugins/ml/models/undeploy_specific_models.yaml b/tests/plugins/ml/models/undeploy_specific_models.yaml new file mode 100644 index 000000000..77d43fe67 --- /dev/null +++ b/tests/plugins/ml/models/undeploy_specific_models.yaml @@ -0,0 +1,77 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the undeployment of specific models from specific nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +version: '>= 2.11' +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Undeploy a model. + path: /_plugins/_ml/models/_undeploy + method: POST + request: + payload: + model_ids: + - ${get_completed_register_model_task.model_id} + response: + status: 200 diff --git a/tests/plugins/ml/models/unload.yaml b/tests/plugins/ml/models/unload.yaml new file mode 100644 index 000000000..4e6d6bcc7 --- /dev/null +++ b/tests/plugins/ml/models/unload.yaml @@ -0,0 +1,74 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the unload (deprecated) of a model from all ML nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Unload a model. + path: /_plugins/_ml/models/{model_id}/_unload + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + response: + status: 200 \ No newline at end of file diff --git a/tests/plugins/ml/models/unload_specific_models.yaml b/tests/plugins/ml/models/unload_specific_models.yaml new file mode 100644 index 000000000..81bae92bf --- /dev/null +++ b/tests/plugins/ml/models/unload_specific_models.yaml @@ -0,0 +1,76 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the unload (deprecated) of specific models from specific nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Unload a model. + path: /_plugins/_ml/models/_unload + method: POST + request: + payload: + model_ids: + - ${get_completed_register_model_task.model_id} + response: + status: 200 From 13b02f5f0c6883edcd6db6aea72c7dd36ef5df59 Mon Sep 17 00:00:00 2001 From: "Daniel (dB.) Doubrovkine" Date: Tue, 17 Dec 2024 08:10:14 -0500 Subject: [PATCH 3/7] Fixed /_search/scroll/{scroll_id}, missing search tests. (#732) * Fixed /_search/scroll. Signed-off-by: dblock * Added tests for GET and POST /_search. Signed-off-by: dblock * Added a test for GET /_search/pipeline and DELETE /_search/pipeline/{id}. Signed-off-by: dblock * Added missing _search/point_in_time tests. Signed-off-by: dblock --------- Signed-off-by: dblock --- CHANGELOG.md | 1 + spec/namespaces/_core.yaml | 3 - tests/default/_core/point_in_time/all.yaml | 33 ++++++ tests/default/_core/search.yaml | 19 ++++ tests/default/_core/search/pipeline.yaml | 33 ++++++ .../response_processor/rename_field.yaml | 13 +-- tests/default/_core/search/point_in_time.yaml | 37 ++++++ tests/default/_core/search/scroll.yaml | 107 ++++++++++++++++++ tests/default/indices/search.yaml | 38 +++++++ .../default/indices/search/point_in_time.yaml | 30 +++++ 10 files changed, 301 insertions(+), 13 deletions(-) create mode 100644 tests/default/_core/point_in_time/all.yaml create mode 100644 tests/default/_core/search.yaml create mode 100644 tests/default/_core/search/pipeline.yaml create mode 100644 tests/default/_core/search/point_in_time.yaml create mode 100644 tests/default/_core/search/scroll.yaml create mode 100644 tests/default/indices/search.yaml create mode 100644 tests/default/indices/search/point_in_time.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 75eb79986..8a53a2668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Fixed snapshot status numeric property types ([#729](https://github.com/opensearch-project/opensearch-api-specification/pull/729)) - Fixed request schema for `PATCH /_plugins/_security/api/nodesdn` ([#731](https://github.com/opensearch-project/opensearch-api-specification/pull/731)) - Fixed response schema for `GET /_plugins/_security/api/nodesdn/{cluster_name}` ([#731](https://github.com/opensearch-project/opensearch-api-specification/pull/731)) +- Fixed request body for `/_search/scroll/{scroll_id}` ([#732](https://github.com/opensearch-project/opensearch-api-specification/pull/732)) ### Changed - Changed `tasks._common:TaskInfo` and `tasks._common:TaskGroup` to be composed of a `tasks._common:TaskInfoBase` ([#683](https://github.com/opensearch-project/opensearch-api-specification/pull/683)) diff --git a/spec/namespaces/_core.yaml b/spec/namespaces/_core.yaml index a1c0e68b0..229fc9e55 100644 --- a/spec/namespaces/_core.yaml +++ b/spec/namespaces/_core.yaml @@ -2523,9 +2523,6 @@ components: $ref: '../schemas/_common.yaml#/components/schemas/Duration' scroll_id: $ref: '../schemas/_common.yaml#/components/schemas/ScrollId' - required: - - scroll_id - description: The scroll ID if not passed by URL or query parameter. search: content: application/json: diff --git a/tests/default/_core/point_in_time/all.yaml b/tests/default/_core/point_in_time/all.yaml new file mode 100644 index 000000000..86ff71e03 --- /dev/null +++ b/tests/default/_core/point_in_time/all.yaml @@ -0,0 +1,33 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test point-in-time. +version: '>= 2.4' +epilogues: + - path: /_search/point_in_time/_all + method: DELETE + - path: /movies + method: DELETE + status: [200, 404] +prologues: + - path: /_bulk + method: POST + parameters: + refresh: true + request: + content_type: application/x-ndjson + payload: + - {create: {_index: movies}} + - {title: The Cruise, year: 1998} + - {create: {_index: movies}} + - {title: Drive, year: 1960} + - path: /movies/_search/point_in_time + method: POST + parameters: + keep_alive: 1m +chapters: + - synopsis: Get all point in time. + path: /_search/point_in_time/_all + method: GET + - synopsis: Delete all point in time. + path: /_search/point_in_time/_all + method: DELETE diff --git a/tests/default/_core/search.yaml b/tests/default/_core/search.yaml new file mode 100644 index 000000000..88072e844 --- /dev/null +++ b/tests/default/_core/search.yaml @@ -0,0 +1,19 @@ +$schema: ../../../json_schemas/test_story.schema.yaml + +description: Test search. +chapters: + - synopsis: Search across all indexes (GET). + path: /_search + method: GET + request: + payload: + query: + match_all: {} + - synopsis: Search across all indexes (POST). + path: /_search + method: POST + request: + payload: + query: + match_all: {} + \ No newline at end of file diff --git a/tests/default/_core/search/pipeline.yaml b/tests/default/_core/search/pipeline.yaml new file mode 100644 index 000000000..eab34717f --- /dev/null +++ b/tests/default/_core/search/pipeline.yaml @@ -0,0 +1,33 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the creation of a search pipeline. +version: '>= 2.9' +epilogues: + - path: /_search/pipeline/empty-pipeline + method: DELETE + status: [200, 404] +chapters: + - synopsis: Create search pipeline. + path: /_search/pipeline/{id} + method: PUT + parameters: + id: empty-pipeline + request: + payload: {} + response: + status: 200 + payload: + acknowledged: true + - synopsis: Query all pipelines. + path: /_search/pipeline + method: GET + - synopsis: Query created pipeline. + path: /_search/pipeline/{id} + method: GET + parameters: + id: empty-pipeline + - synopsis: Delete created pipeline. + path: /_search/pipeline/{id} + method: DELETE + parameters: + id: empty-pipeline diff --git a/tests/default/_core/search/pipeline/response_processor/rename_field.yaml b/tests/default/_core/search/pipeline/response_processor/rename_field.yaml index 388d1414a..d2b05957b 100644 --- a/tests/default/_core/search/pipeline/response_processor/rename_field.yaml +++ b/tests/default/_core/search/pipeline/response_processor/rename_field.yaml @@ -13,7 +13,7 @@ prologues: name: Drive status: [201] epilogues: - - path: /_search/pipeline/names_pipeline + - path: /_search/pipeline/rename-field method: DELETE status: [200, 404] - path: /movies @@ -24,7 +24,7 @@ chapters: path: /_search/pipeline/{id} method: PUT parameters: - id: names_pipeline + id: rename-field request: payload: response_processors: @@ -35,13 +35,6 @@ chapters: status: 200 payload: acknowledged: true - - synopsis: Query created pipeline. - path: /_search/pipeline/{id} - method: GET - parameters: - id: names_pipeline - response: - status: 200 - synopsis: Search. warnings: multiple-paths-detected: false @@ -49,7 +42,7 @@ chapters: method: GET parameters: index: movies - search_pipeline: names_pipeline + search_pipeline: rename-field response: status: 200 payload: diff --git a/tests/default/_core/search/point_in_time.yaml b/tests/default/_core/search/point_in_time.yaml new file mode 100644 index 000000000..7eba25818 --- /dev/null +++ b/tests/default/_core/search/point_in_time.yaml @@ -0,0 +1,37 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test point-in-time. +version: '>= 2.4' +epilogues: + - path: /_search/point_in_time/_all + method: DELETE + - path: /movies + method: DELETE + status: [200, 404] +prologues: + - path: /_bulk + method: POST + parameters: + refresh: true + request: + content_type: application/x-ndjson + payload: + - {create: {_index: movies}} + - {title: The Cruise, year: 1998} + - {create: {_index: movies}} + - {title: Drive, year: 1960} + - path: /movies/_search/point_in_time + id: pit + method: POST + parameters: + keep_alive: 1m + output: + id: payload.pit_id +chapters: + - synopsis: Delete all pits. + path: /_search/point_in_time + request: + payload: + pit_id: + - ${pit.id} + method: DELETE diff --git a/tests/default/_core/search/scroll.yaml b/tests/default/_core/search/scroll.yaml new file mode 100644 index 000000000..fb4baccd1 --- /dev/null +++ b/tests/default/_core/search/scroll.yaml @@ -0,0 +1,107 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test search scroll. +prologues: + - path: /_bulk + method: POST + parameters: + refresh: true + request: + content_type: application/x-ndjson + payload: + - {create: {_index: movies}} + - {title: The Lion King, year: 1994} + - {create: {_index: movies}} + - {title: Drive, year: 2011} + - {create: {_index: movies}} + - {title: Frozen, year: 2013} + - {create: {_index: movies}} + - {title: Moneyball, year: 2011} + - {create: {_index: movies}} + - {title: The Cruise, year: 1998} + - path: /movies/_search + method: GET + id: scroll + parameters: + scroll: 10m + request: + payload: + query: + match_all: {} + size: 1 + output: + scroll_id: payload._scroll_id +epilogues: + - path: /_search/scroll/_all + method: DELETE + - path: /movies + method: DELETE + status: [200, 404] +chapters: + - synopsis: Get the next batch of results (GET). + method: GET + path: /_search/scroll + request: + payload: + scroll: 10m + scroll_id: ${scroll.scroll_id} + response: + status: 200 + payload: + hits: + hits: + - _index: movies + _source: + title: Drive + - synopsis: Get the next batch of results (POST). + method: POST + path: /_search/scroll + request: + payload: + scroll: 10m + scroll_id: ${scroll.scroll_id} + response: + status: 200 + payload: + hits: + hits: + - _index: movies + _source: + title: Frozen + - synopsis: Get the next batch of results (GET). + method: GET + path: /_search/scroll/{scroll_id} + parameters: + scroll_id: ${scroll.scroll_id} + request: + payload: + scroll: 10m + response: + status: 200 + payload: + hits: + hits: + - _index: movies + _source: + title: Moneyball + - synopsis: Get the next batch of results (POST). + method: POST + path: /_search/scroll/{scroll_id} + parameters: + scroll_id: ${scroll.scroll_id} + request: + payload: + scroll: 10m + response: + status: 200 + payload: + hits: + hits: + - _index: movies + _source: + title: The Cruise + - synopsis: Delete the scroll. + method: DELETE + path: /_search/scroll/{scroll_id} + parameters: + scroll_id: ${scroll.scroll_id} diff --git a/tests/default/indices/search.yaml b/tests/default/indices/search.yaml new file mode 100644 index 000000000..b3f78261b --- /dev/null +++ b/tests/default/indices/search.yaml @@ -0,0 +1,38 @@ +$schema: ../../../json_schemas/test_story.schema.yaml + +description: Test search. +prologues: + - path: /_bulk + method: POST + parameters: + refresh: true + request: + content_type: application/x-ndjson + payload: + - {create: {_index: movies, _id: movie1}} + - {director: Quentin Tarantino, title: Pulp Fiction, year: 1994} + - {create: {_index: movies, _id: movie2}} + - {director: Christopher Nolan, title: Inception, year: 2010} +epilogues: + - path: /movies + method: DELETE + status: [200, 404] +chapters: + - synopsis: Search in an index (GET). + path: /{index}/_search + method: GET + parameters: + index: movies + request: + payload: + query: + match_all: {} + - synopsis: Search across all indices (POST). + path: /{index}/_search + method: POST + parameters: + index: movies + request: + payload: + query: + match_all: {} diff --git a/tests/default/indices/search/point_in_time.yaml b/tests/default/indices/search/point_in_time.yaml new file mode 100644 index 000000000..c626db504 --- /dev/null +++ b/tests/default/indices/search/point_in_time.yaml @@ -0,0 +1,30 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test point-in-time. +version: '>= 2.4' +epilogues: + - path: /_search/point_in_time/_all + method: DELETE + - path: /movies + method: DELETE + status: [200, 404] +prologues: + - path: /_bulk + method: POST + parameters: + refresh: true + request: + content_type: application/x-ndjson + payload: + - {create: {_index: movies}} + - {title: The Cruise, year: 1998} + - {create: {_index: movies}} + - {title: Drive, year: 1960} +chapters: + - synopsis: Create a point in time. + path: /{index}/_search/point_in_time + method: POST + parameters: + index: + - movies + keep_alive: 1m From 0f2c91f4164e540232fa58fc6d11cee92d6437a7 Mon Sep 17 00:00:00 2001 From: "Daniel (dB.) Doubrovkine" Date: Tue, 17 Dec 2024 08:10:36 -0500 Subject: [PATCH 4/7] Added tests for /_template/{name}. (#736) Signed-off-by: dblock --- tests/default/_core/template.yaml | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/default/_core/template.yaml diff --git a/tests/default/_core/template.yaml b/tests/default/_core/template.yaml new file mode 100644 index 000000000..4096d9568 --- /dev/null +++ b/tests/default/_core/template.yaml @@ -0,0 +1,73 @@ +$schema: ../../../json_schemas/test_story.schema.yaml + +description: Test templates. +epilogues: + - path: /_template/daily_logs + method: DELETE + status: [200, 404] +chapters: + - synopsis: Create a template. + path: /_template/{name} + method: POST + parameters: + name: daily_logs + request: + payload: + index_patterns: + - 'logs*' + settings: + number_of_shards: 2 + number_of_replicas: 2 + response: + status: 200 + - synopsis: Update a template. + path: /_template/{name} + method: PUT + parameters: + name: daily_logs + request: + payload: + index_patterns: + - 'logs*' + aliases: + my_logs: {} + settings: + number_of_shards: 4 + number_of_replicas: 4 + mappings: + properties: + timestamp: + type: date + format: yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis + value: + type: double + response: + status: 200 + - synopsis: Retrieve templates. + path: /_template + method: GET + - synopsis: Retrieve a template. + path: /_template/{name} + method: GET + parameters: + name: daily_logs + response: + status: 200 + payload: + daily_logs: + index_patterns: + - logs* + settings: + index: + number_of_shards: '4' + number_of_replicas: '4' + - synopsis: Check that a template exists. + path: /_template/{name} + method: HEAD + parameters: + name: daily_logs + - synopsis: Delete a template. + path: /_template/{name} + method: DELETE + parameters: + name: daily_logs From 5d7569fde4524ebacbdefe5a1d27c9af5a8138ea Mon Sep 17 00:00:00 2001 From: "Daniel (dB.) Doubrovkine" Date: Tue, 17 Dec 2024 11:54:54 -0500 Subject: [PATCH 5/7] Added tests for /_validate/query. (#739) * Added tests for /_validate/query. Signed-off-by: dblock * Added retry for https://github.com/opensearch-project/opensearch-api-specification/issues/738. Signed-off-by: dblock --------- Signed-off-by: dblock --- tests/default/_core/validate/query.yaml | 17 +++++++++++++++++ tests/default/indices/validate/query.yaml | 23 +++++------------------ tests/plugins/security/api/nodesdn.yaml | 2 ++ 3 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 tests/default/_core/validate/query.yaml diff --git a/tests/default/_core/validate/query.yaml b/tests/default/_core/validate/query.yaml new file mode 100644 index 000000000..1c5849c01 --- /dev/null +++ b/tests/default/_core/validate/query.yaml @@ -0,0 +1,17 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test validating queries. +chapters: + - synopsis: Validate a query. + path: /_validate/query + method: + - GET + - POST + request: + payload: + query: + match_all: {} + response: + status: 200 + payload: + valid: true diff --git a/tests/default/indices/validate/query.yaml b/tests/default/indices/validate/query.yaml index 264579058..55ced1fb8 100644 --- a/tests/default/indices/validate/query.yaml +++ b/tests/default/indices/validate/query.yaml @@ -1,6 +1,6 @@ $schema: ../../../../json_schemas/test_story.schema.yaml -description: Test validating queries for a specific index using both GET and POST methods. +description: Test validating queries for a specific index. epilogues: - path: /movies method: DELETE @@ -18,9 +18,11 @@ prologues: - {create: {_index: movies, _id: movie2}} - {director: Nicolas Winding Refn, title: Drive, year: 1960} chapters: - - synopsis: Validate a match query (GET). + - synopsis: Validate a match query. path: /{index}/_validate/query - method: GET + method: + - GET + - POST parameters: index: movies request: @@ -32,18 +34,3 @@ chapters: status: 200 payload: valid: true - - - synopsis: Validate a match query (POST). - path: /{index}/_validate/query - method: POST - parameters: - index: movies - request: - payload: - query: - match: - title: Drive - response: - status: 200 - payload: - valid: true \ No newline at end of file diff --git a/tests/plugins/security/api/nodesdn.yaml b/tests/plugins/security/api/nodesdn.yaml index 176a748c9..6a4611ef3 100644 --- a/tests/plugins/security/api/nodesdn.yaml +++ b/tests/plugins/security/api/nodesdn.yaml @@ -15,6 +15,8 @@ chapters: payload: nodes_dn: - CN=cluster.example.com + retry: + count: 3 response: status: 201 payload: From 49b2e5071748ecf0db3f5c25f02c8c1b913a4258 Mon Sep 17 00:00:00 2001 From: Nathalie Jonathan Date: Tue, 17 Dec 2024 09:41:42 -0800 Subject: [PATCH 6/7] Fixed lint and directory path error. Signed-off-by: Nathalie Jonathan --- spec/namespaces/ml.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/spec/namespaces/ml.yaml b/spec/namespaces/ml.yaml index aa576e787..d65c5eb92 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -90,6 +90,8 @@ paths: description: Undeploys a model. parameters: - $ref: '#/components/parameters/ml.undeploy_model::path.model_id' + requestBody: + $ref: '#/components/requestBodies/ml.undeploy_model' responses: '200': $ref: '#/components/responses/ml.undeploy_model@200' @@ -110,8 +112,11 @@ paths: deprecated: true x-version-deprecated: 2.7.0 x-deprecation-message: Use `undeploy_model` instead. + description: Unloads a model. parameters: - $ref: '#/components/parameters/ml.unload_model::path.model_id' + requestBody: + $ref: '#/components/requestBodies/ml.unload_model' responses: '200': $ref: '#/components/responses/ml.unload_model@200' @@ -122,6 +127,7 @@ paths: deprecated: true x-version-deprecated: 2.7.0 x-deprecation-message: Use `undeploy_model` instead. + description: Unloads a model. requestBody: $ref: '#/components/requestBodies/ml.unload_model' responses: @@ -313,11 +319,11 @@ components: node_ids: type: array items: - $ref: '_common.yaml#/components/schemas/Id' + $ref: '../schemas/_common.yaml#/components/schemas/Id' model_ids: type: array items: - $ref: '_common.yaml#/components/schemas/Id' + $ref: '../schemas/_common.yaml#/components/schemas/Id' required: - model_ids ml.unload_model: @@ -329,11 +335,11 @@ components: node_ids: type: array items: - $ref: '_common.yaml#/components/schemas/Id' + $ref: '../schemas/_common.yaml#/components/schemas/Id' model_ids: type: array items: - $ref: '_common.yaml#/components/schemas/Id' + $ref: '../schemas/_common.yaml#/components/schemas/Id' required: - model_ids ml.create_connector: From 1809c514ca9801b018b5b758c1843ea06d986c90 Mon Sep 17 00:00:00 2001 From: Nathalie Jonathan Date: Tue, 17 Dec 2024 14:42:53 -0800 Subject: [PATCH 7/7] Added ML Model APIs (load, upload, create metadata). Signed-off-by: Nathalie Jonathan --- CHANGELOG.md | 2 +- spec/namespaces/ml.yaml | 159 ++++++++++++++++++++++++++ tests/plugins/ml/models/load.yaml | 79 +++++++++++++ tests/plugins/ml/models/metadata.yaml | 75 ++++++++++++ tests/plugins/ml/models/upload.yaml | 56 +++++++++ 5 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/ml/models/load.yaml create mode 100644 tests/plugins/ml/models/metadata.yaml create mode 100644 tests/plugins/ml/models/upload.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a53a2668..89f693614 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added response schema for `GET /_plugins/_knn/warmup/{index}` ([#717](https://github.com/opensearch-project/opensearch-api-specification/pull/717)) - Added support for multiple test verbs ([#724](https://github.com/opensearch-project/opensearch-api-specification/pull/724)) - Added support for using a certificate and key in tests ([#731](https://github.com/opensearch-project/opensearch-api-specification/pull/731)) -- Added `GET /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/_search`, `PUT /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/{model_id}/_unload`, `POST /_plugins/_ml/models/_unload`, and `POST /_plugins/_ml/models/_undeploy` ([#733](https://github.com/opensearch-project/opensearch-api-specification/pull/733)) +- Added `GET /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/_search`, `PUT /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/{model_id}/_unload`, `POST /_plugins/_ml/models/_unload`, `POST /_plugins/_ml/models/_undeploy`, `POST /_plugins/_ml/models/_upload`,`POST /_plugins/_ml/models/{model_id}/_load`, and `POST /_plugins/_ml/models/meta` ([#733](https://github.com/opensearch-project/opensearch-api-specification/pull/733)) ### Removed - Removed unsupported `_common.mapping:SourceField`'s `mode` field and associated `_common.mapping:SourceFieldMode` enum ([#652](https://github.com/opensearch-project/opensearch-api-specification/pull/652)) diff --git a/spec/namespaces/ml.yaml b/spec/namespaces/ml.yaml index d65c5eb92..8cecd7c88 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -43,6 +43,29 @@ paths: responses: '200': $ref: '#/components/responses/ml.register_model@200' + /_plugins/_ml/models/meta: + post: + operationId: ml.create_model_meta.0 + x-operation-group: ml.create_model_meta + description: Creates a model metadata. + requestBody: + $ref: '#/components/requestBodies/ml.create_model_meta' + responses: + '200': + $ref: '#/components/responses/ml.create_model_meta@200' + /_plugins/_ml/models/_upload: + post: + operationId: ml.upload_model.0 + x-operation-group: ml.upload_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `register_model` instead. + description: Registers a model. + requestBody: + $ref: '#/components/requestBodies/ml.upload_model' + responses: + '200': + $ref: '#/components/responses/ml.upload_model@200' /_plugins/_ml/models/{model_id}: get: operationId: ml.get_model.0 @@ -83,6 +106,19 @@ paths: responses: '200': $ref: '#/components/responses/ml.deploy_model@200' + /_plugins/_ml/models/{model_id}/_load: + post: + operationId: ml.load_model.0 + x-operation-group: ml.load_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `deploy_model` instead. + description: Deploys a model. + parameters: + - $ref: '#/components/parameters/ml.load_model::path.model_id' + responses: + '200': + $ref: '#/components/responses/ml.load_model@200' /_plugins/_ml/models/{model_id}/_undeploy: post: operationId: ml.undeploy_model.0 @@ -264,6 +300,72 @@ components: required: - name - version + ml.create_model_meta: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The model name. + version: + type: string + description: The model version. + model_format: + type: string + description: The portable format of the model file. + enum: [ONNX, TORCH_SCRIPT] + model_group_id: + type: string + description: The ID of the model group to which to register the model. + model_content_hash_value: + type: string + description: The model content hash value. + model_config: + $ref: '../schemas/ml._common.yaml#/components/schemas/ModelConfig' + total_chunks: + type: integer + format: int64 + description: The total chunks. + url: + type: string + description: The model URL. + description: + type: string + description: The model description. + required: + - model_config + - model_content_hash_value + - model_format + - name + - total_chunks + - version + ml.upload_model: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The model name. + version: + type: string + description: The model version. + model_format: + type: string + description: The portable format of the model file. + enum: [ONNX, TORCH_SCRIPT] + description: + type: string + description: The model description. + model_group_id: + type: string + description: The ID of the model group to which to register the model. + required: + - name + - version ml.search_models: content: application/json: @@ -430,6 +532,32 @@ components: required: - status - task_id + ml.create_model_meta@200: + content: + application/json: + schema: + type: object + properties: + status: + type: string + model_id: + type: string + required: + - model_id + - status + ml.upload_model@200: + content: + application/json: + schema: + type: object + properties: + status: + type: string + task_id: + type: string + required: + - status + - task_id ml.deploy_model@200: content: application/json: @@ -445,6 +573,31 @@ components: required: - status - task_id + ml.load_model@200: + content: + application/json: + schema: + type: object + properties: + status: + type: string + task_id: + type: string + task_type: + type: string + enum: + - BATCH_INGEST + - BATCH_PREDICTION + - DEPLOY_MODEL + - EXECUTION + - PREDICTION + - REGISTER_MODEL + - TRAINING + - TRAINING_AND_PREDICTION + required: + - status + - task_id + - task_type ml.undeploy_model@200: content: application/json: @@ -548,6 +701,12 @@ components: required: true schema: type: string + ml.load_model::path.model_id: + name: model_id + in: path + required: true + schema: + type: string ml.undeploy_model::path.model_id: name: model_id in: path diff --git a/tests/plugins/ml/models/load.yaml b/tests/plugins/ml/models/load.yaml new file mode 100644 index 000000000..c560e906c --- /dev/null +++ b/tests/plugins/ml/models/load.yaml @@ -0,0 +1,79 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the deployment of a model using load API (deprecated). +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id}/_undeploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + status: [200, 404] + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: load_model + path: /_plugins/_ml/models/{model_id}/_load + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_load_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${load_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Undeploy a model. + path: /_plugins/_ml/models/{model_id}/_undeploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + response: + status: 200 diff --git a/tests/plugins/ml/models/metadata.yaml b/tests/plugins/ml/models/metadata.yaml new file mode 100644 index 000000000..49062cf61 --- /dev/null +++ b/tests/plugins/ml/models/metadata.yaml @@ -0,0 +1,75 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the creation of model metadata. +distributions: + excluded: + - amazon-managed + - amazon-serverless +version: '>= 2.11' +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Create model metadata. + id: model_metadata + path: /_plugins/_ml/models/meta + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + model_content_hash_value: 123abc + total_chunks: 1 + model_config: + all_config: path + model_type: bert + embedding_dimension: 384 + framework_type: sentence_transformers + response: + status: 200 + output: + model_id: payload.model_id + - synopsis: Wait to get completed task. + id: get_completed_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 5 + wait: 30000 + - synopsis: Get model. + path: /_plugins/_ml/models/{model_id} + method: GET + parameters: + model_id: ${get_completed_task.model_id} + response: + status: 200 + - synopsis: Delete model. + path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_task.model_id} + method: DELETE diff --git a/tests/plugins/ml/models/upload.yaml b/tests/plugins/ml/models/upload.yaml new file mode 100644 index 000000000..6efafdb48 --- /dev/null +++ b/tests/plugins/ml/models/upload.yaml @@ -0,0 +1,56 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the creation of models using upload API (deprecated). +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +epilogues: + - path: /_plugins/_ml/models/{model_id} + method: DELETE + status: [200, 404] + parameters: + model_id: ${get_completed_task.model_id} +chapters: + - synopsis: Register model. + id: upload_model + path: /_plugins/_ml/models/_upload + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + response: + status: 200 + output: + task_id: payload.task_id + - synopsis: Wait to get completed task. + id: get_completed_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${upload_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 5 + wait: 30000 + - synopsis: Get model. + path: /_plugins/_ml/models/{model_id} + method: GET + parameters: + model_id: ${get_completed_task.model_id} + response: + status: 200 + - synopsis: Delete model. + path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_task.model_id} + method: DELETE