|
16 | 16 | LogLevel, |
17 | 17 | PipelineLog, |
18 | 18 | PipelineValidationResult, |
| 19 | + PipelineVersion, |
19 | 20 | ValidationError, |
20 | 21 | ) |
21 | 22 | from deepset_mcp.api.pipeline.protocols import PipelineResourceProtocol |
@@ -161,54 +162,149 @@ async def create(self, pipeline_name: str, yaml_config: str) -> NoContentRespons |
161 | 162 |
|
162 | 163 | return NoContentResponse(message="Pipeline created successfully.") |
163 | 164 |
|
164 | | - async def update( |
| 165 | + async def list_versions( |
165 | 166 | self, |
166 | 167 | pipeline_name: str, |
167 | | - updated_pipeline_name: str | None = None, |
168 | | - yaml_config: str | None = None, |
169 | | - ) -> NoContentResponse: |
170 | | - """Update name and/or YAML config of an existing pipeline. |
171 | | -
|
172 | | - :param pipeline_name: Current name of the pipeline. |
173 | | - :param updated_pipeline_name: New name for the pipeline (optional). |
174 | | - :param yaml_config: New YAML configuration (optional). |
175 | | - :returns: NoContentResponse indicating successful update. |
176 | | - :raises ValueError: If neither updated_pipeline_name nor yaml_config is provided. |
| 168 | + limit: int = 10, |
| 169 | + after: str | None = None, |
| 170 | + ) -> PaginatedResponse[PipelineVersion]: |
| 171 | + """List versions of a pipeline, most recent first. |
| 172 | +
|
| 173 | + :param pipeline_name: Name of the pipeline. |
| 174 | + :param limit: Maximum number of versions to return per page. |
| 175 | + :param after: Cursor (version_id UUID) for the next page. |
| 176 | + :returns: A `PaginatedResponse` containing pipeline versions. |
177 | 177 | """ |
178 | | - # Handle name update first if any |
179 | | - if updated_pipeline_name is not None: |
180 | | - name_resp = await self._client.request( |
181 | | - endpoint=f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/{quote(pipeline_name, safe='')}", |
182 | | - method="PATCH", |
183 | | - data={"name": updated_pipeline_name}, |
184 | | - ) |
| 178 | + request_params: dict[str, Any] = {"limit": limit, "order": "DESC", "field": "version_number"} |
| 179 | + if after is not None: |
| 180 | + request_params["after"] = after |
185 | 181 |
|
186 | | - raise_for_status(name_resp) |
| 182 | + page = await self._list_versions_api_call(pipeline_name, **request_params) |
| 183 | + page._inject_paginator( |
| 184 | + fetch_func=lambda **kwargs: self._list_versions_api_call(pipeline_name, **kwargs), |
| 185 | + base_args={"limit": limit, "order": "DESC", "field": "version_number"}, |
| 186 | + cursor_param="after", |
| 187 | + ) |
| 188 | + return page |
187 | 189 |
|
188 | | - pipeline_name = updated_pipeline_name |
| 190 | + async def _list_versions_api_call(self, pipeline_name: str, **kwargs: Any) -> PaginatedResponse[PipelineVersion]: |
| 191 | + resp = await self._client.request( |
| 192 | + endpoint=( |
| 193 | + f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/{quote(pipeline_name, safe='')}/versions" |
| 194 | + ), |
| 195 | + method="GET", |
| 196 | + params=kwargs, |
| 197 | + ) |
| 198 | + raise_for_status(resp) |
| 199 | + if resp.json is None: |
| 200 | + raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None) |
| 201 | + return PaginatedResponse[PipelineVersion].create_with_cursor_field(resp.json, "version_id") |
189 | 202 |
|
190 | | - if yaml_config is None: |
191 | | - return NoContentResponse(message="Pipeline name updated successfully.") |
| 203 | + async def create_version( |
| 204 | + self, |
| 205 | + pipeline_name: str, |
| 206 | + config_yaml: str, |
| 207 | + description: str | None = None, |
| 208 | + is_draft: bool = False, |
| 209 | + ) -> PipelineVersion: |
| 210 | + """Create a new version of a pipeline. |
| 211 | +
|
| 212 | + :param pipeline_name: Name of the pipeline. |
| 213 | + :param config_yaml: YAML configuration for the new version. |
| 214 | + :param description: Optional description of the version. |
| 215 | + :param is_draft: Whether to create the version as a draft. |
| 216 | + :returns: The newly created PipelineVersion. |
| 217 | + """ |
| 218 | + data: dict[str, Any] = {"config_yaml": config_yaml, "is_draft": is_draft} |
| 219 | + if description is not None: |
| 220 | + data["description"] = description |
192 | 221 |
|
193 | | - if yaml_config is not None: |
194 | | - yaml_resp = await self._client.request( |
195 | | - endpoint=( |
196 | | - f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/{quote(pipeline_name, safe='')}/yaml" |
197 | | - ), |
198 | | - method="PUT", |
199 | | - data={"query_yaml": yaml_config}, |
200 | | - ) |
| 222 | + resp = await self._client.request( |
| 223 | + endpoint=( |
| 224 | + f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/{quote(pipeline_name, safe='')}/versions" |
| 225 | + ), |
| 226 | + method="POST", |
| 227 | + data=data, |
| 228 | + ) |
| 229 | + raise_for_status(resp) |
| 230 | + if resp.json is None: |
| 231 | + raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None) |
| 232 | + return PipelineVersion.model_validate(resp.json) |
201 | 233 |
|
202 | | - raise_for_status(yaml_resp) |
| 234 | + async def get_version(self, pipeline_name: str, version_id: str) -> PipelineVersion: |
| 235 | + """Fetch a specific version of a pipeline. |
203 | 236 |
|
204 | | - if updated_pipeline_name is not None: |
205 | | - response = NoContentResponse(message="Pipeline name and YAML updated successfully.") |
206 | | - else: |
207 | | - response = NoContentResponse(message="Pipeline YAML updated successfully.") |
| 237 | + :param pipeline_name: Name of the pipeline. |
| 238 | + :param version_id: UUID of the version to fetch. |
| 239 | + :returns: The requested PipelineVersion. |
| 240 | + """ |
| 241 | + resp = await self._client.request( |
| 242 | + endpoint=( |
| 243 | + f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/" |
| 244 | + f"{quote(pipeline_name, safe='')}/versions/{quote(version_id, safe='')}" |
| 245 | + ), |
| 246 | + ) |
| 247 | + raise_for_status(resp) |
| 248 | + if resp.json is None: |
| 249 | + raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None) |
| 250 | + return PipelineVersion.model_validate(resp.json) |
| 251 | + |
| 252 | + async def restore_version(self, pipeline_name: str, version_id: str) -> PipelineVersion: |
| 253 | + """Restore a pipeline to a previous version. |
| 254 | +
|
| 255 | + :param pipeline_name: Name of the pipeline. |
| 256 | + :param version_id: UUID of the version to restore. |
| 257 | + :returns: The restored PipelineVersion. |
| 258 | + """ |
| 259 | + resp = await self._client.request( |
| 260 | + endpoint=( |
| 261 | + f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/" |
| 262 | + f"{quote(pipeline_name, safe='')}/versions/{quote(version_id, safe='')}/restore" |
| 263 | + ), |
| 264 | + method="POST", |
| 265 | + ) |
| 266 | + raise_for_status(resp) |
| 267 | + if resp.json is None: |
| 268 | + raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None) |
| 269 | + return PipelineVersion.model_validate(resp.json) |
208 | 270 |
|
209 | | - return response |
| 271 | + async def patch_version( |
| 272 | + self, |
| 273 | + pipeline_name: str, |
| 274 | + version_id: str, |
| 275 | + config_yaml: str | None = None, |
| 276 | + description: str | None = None, |
| 277 | + is_draft: bool | None = None, |
| 278 | + ) -> PipelineVersion: |
| 279 | + """Patch fields of an existing pipeline version. |
| 280 | +
|
| 281 | + :param pipeline_name: Name of the pipeline. |
| 282 | + :param version_id: UUID of the version to patch. |
| 283 | + :param config_yaml: New YAML configuration (optional). |
| 284 | + :param description: New description (optional). |
| 285 | + :param is_draft: New draft status (optional). |
| 286 | + :returns: The updated PipelineVersion. |
| 287 | + """ |
| 288 | + data: dict[str, Any] = {} |
| 289 | + if config_yaml is not None: |
| 290 | + data["config_yaml"] = config_yaml |
| 291 | + if description is not None: |
| 292 | + data["description"] = description |
| 293 | + if is_draft is not None: |
| 294 | + data["is_draft"] = is_draft |
210 | 295 |
|
211 | | - raise ValueError("Either `updated_pipeline_name` or `yaml_config` must be provided.") |
| 296 | + resp = await self._client.request( |
| 297 | + endpoint=( |
| 298 | + f"v1/workspaces/{quote(self._workspace, safe='')}/pipelines/" |
| 299 | + f"{quote(pipeline_name, safe='')}/versions/{quote(version_id, safe='')}" |
| 300 | + ), |
| 301 | + method="PATCH", |
| 302 | + data=data, |
| 303 | + ) |
| 304 | + raise_for_status(resp) |
| 305 | + if resp.json is None: |
| 306 | + raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None) |
| 307 | + return PipelineVersion.model_validate(resp.json) |
212 | 308 |
|
213 | 309 | async def get_logs( |
214 | 310 | self, |
|
0 commit comments