diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 1eb290ef5ae3..d947c7b1f9c7 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -167,6 +167,23 @@ export interface paths { /** For internal use, this endpoint may change without warning. */ get: operations["show_inheritance_chain_api_datasets__dataset_id__inheritance_chain_get"]; }; + "/api/datasets/{dataset_id}/metrics": { + /** + * Return job metrics for specified job. + * @deprecated + */ + get: operations["get_metrics_api_datasets__dataset_id__metrics_get"]; + }; + "/api/datasets/{dataset_id}/parameters_display": { + /** + * Resolve parameters as a list for nested display. + * @deprecated + * @description Resolve parameters as a list for nested display. + * This API endpoint is unstable and tied heavily to Galaxy's JS client code, + * this endpoint will change frequently. + */ + get: operations["resolve_parameters_display_api_datasets__dataset_id__parameters_display_get"]; + }; "/api/datasets/{dataset_id}/permissions": { /** * Set permissions of the given history dataset to the given role ids. @@ -893,16 +910,40 @@ export interface paths { /** Index */ get: operations["index_api_jobs_get"]; }; - "/api/jobs/{id}": { + "/api/jobs/search": { /** - * Show - * @description Return dictionary containing description of job data - * - * Parameters - * - id: ID of job to return - * - full: Return extra information ? + * Return jobs for current user + * @description This method is designed to scan the list of previously run jobs and find records of jobs that had + * the exact some input parameters and datasets. This can be used to minimize the amount of repeated work, and simply + * recycle the old results. */ - get: operations["show_api_jobs__id__get"]; + post: operations["search_jobs_api_jobs_search_post"]; + }; + "/api/jobs/{job_id}": { + /** Return dictionary containing description of job data. */ + get: operations["show_job_api_jobs__job_id__get"]; + /** Cancels specified job */ + delete: operations["cancel_job_api_jobs__job_id__delete"]; + }; + "/api/jobs/{job_id}/common_problems": { + /** Check inputs and job for common potential problems to aid in error reporting */ + get: operations["check_common_problems_api_jobs__job_id__common_problems_get"]; + }; + "/api/jobs/{job_id}/destination_params": { + /** Return destination parameters for specified job. */ + get: operations["destination_params_job_api_jobs__job_id__destination_params_get"]; + }; + "/api/jobs/{job_id}/error": { + /** Submits a bug report via the API. */ + post: operations["report_error_api_jobs__job_id__error_post"]; + }; + "/api/jobs/{job_id}/inputs": { + /** Returns input datasets created by a job. */ + get: operations["get_inputs_api_jobs__job_id__inputs_get"]; + }; + "/api/jobs/{job_id}/metrics": { + /** Return job metrics for specified job. */ + get: operations["get_metrics_api_jobs__job_id__metrics_get"]; }; "/api/jobs/{job_id}/oidc-tokens": { /** @@ -911,6 +952,23 @@ export interface paths { */ get: operations["get_token_api_jobs__job_id__oidc_tokens_get"]; }; + "/api/jobs/{job_id}/outputs": { + /** Returns output datasets created by a job. */ + get: operations["get_outputs_api_jobs__job_id__outputs_get"]; + }; + "/api/jobs/{job_id}/parameters_display": { + /** + * Resolve parameters as a list for nested display. + * @description Resolve parameters as a list for nested display. + * This API endpoint is unstable and tied heavily to Galaxy's JS client code, + * this endpoint will change frequently. + */ + get: operations["resolve_parameters_display_api_jobs__job_id__parameters_display_get"]; + }; + "/api/jobs/{job_id}/resume": { + /** Resumes a paused job. */ + put: operations["resume_paused_job_api_jobs__job_id__resume_put"]; + }; "/api/libraries": { /** * Returns a list of summary data for all libraries. @@ -1729,10 +1787,7 @@ export interface components { */ link: string; }; - /** - * AnonUserModel - * @description Base model definition with common configuration used by all derived models. - */ + /** AnonUserModel */ AnonUserModel: { /** * Nice total disc usage @@ -1750,10 +1805,7 @@ export interface components { */ total_disk_usage: number; }; - /** - * ArchiveHistoryRequestPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** ArchiveHistoryRequestPayload */ ArchiveHistoryRequestPayload: { /** * Export Record ID @@ -1984,10 +2036,7 @@ export interface components { */ url: string; }; - /** - * AsyncFile - * @description Base model definition with common configuration used by all derived models. - */ + /** AsyncFile */ AsyncFile: { /** * Storage Request Id @@ -1996,10 +2045,7 @@ export interface components { storage_request_id: string; task: components["schemas"]["AsyncTaskResultSummary"]; }; - /** - * AsyncTaskResultSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** AsyncTaskResultSummary */ AsyncTaskResultSummary: { /** * ID @@ -2040,10 +2086,7 @@ export interface components { ) | ("cloud" | "quota" | "no_quota" | "restricted"); }; - /** - * BasicRoleModel - * @description Base model definition with common configuration used by all derived models. - */ + /** BasicRoleModel */ BasicRoleModel: { /** * ID @@ -2092,10 +2135,7 @@ export interface components { /** Targets */ targets: Record; }; - /** - * BroadcastNotificationContent - * @description Base model definition with common configuration used by all derived models. - */ + /** BroadcastNotificationContent */ BroadcastNotificationContent: { /** * Action links @@ -2216,10 +2256,7 @@ export interface components { */ variant: components["schemas"]["NotificationVariant"]; }; - /** - * BrowsableFilesSourcePlugin - * @description Base model definition with common configuration used by all derived models. - */ + /** BrowsableFilesSourcePlugin */ BrowsableFilesSourcePlugin: { /** * Browsable @@ -2273,19 +2310,13 @@ export interface components { */ writable: boolean; }; - /** - * BulkOperationItemError - * @description Base model definition with common configuration used by all derived models. - */ + /** BulkOperationItemError */ BulkOperationItemError: { /** Error */ error: string; item: components["schemas"]["EncodedHistoryContentItem"]; }; - /** - * ChangeDatatypeOperationParams - * @description Base model definition with common configuration used by all derived models. - */ + /** ChangeDatatypeOperationParams */ ChangeDatatypeOperationParams: { /** Datatype */ datatype: string; @@ -2295,10 +2326,7 @@ export interface components { */ type: "change_datatype"; }; - /** - * ChangeDbkeyOperationParams - * @description Base model definition with common configuration used by all derived models. - */ + /** ChangeDbkeyOperationParams */ ChangeDbkeyOperationParams: { /** Dbkey */ dbkey: string; @@ -2308,10 +2336,7 @@ export interface components { */ type: "change_dbkey"; }; - /** - * CheckForUpdatesResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** CheckForUpdatesResponse */ CheckForUpdatesResponse: { /** * Message @@ -2341,10 +2366,7 @@ export interface components { */ type: string; }; - /** - * CleanableItemsSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** CleanableItemsSummary */ CleanableItemsSummary: { /** * Total Items @@ -2357,18 +2379,12 @@ export interface components { */ total_size: number; }; - /** - * CleanupStorageItemsRequest - * @description Base model definition with common configuration used by all derived models. - */ + /** CleanupStorageItemsRequest */ CleanupStorageItemsRequest: { /** Item Ids */ item_ids: string[]; }; - /** - * CloudDatasets - * @description Base model definition with common configuration used by all derived models. - */ + /** CloudDatasets */ CloudDatasets: { /** * Authentication ID @@ -2399,10 +2415,7 @@ export interface components { */ overwrite_existing?: boolean; }; - /** - * CloudDatasetsResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** CloudDatasetsResponse */ CloudDatasetsResponse: { /** * Bucket @@ -2420,10 +2433,7 @@ export interface components { */ sent_dataset_labels: string[]; }; - /** - * CloudObjects - * @description Base model definition with common configuration used by all derived models. - */ + /** CloudObjects */ CloudObjects: { /** * Authentication ID @@ -2453,10 +2463,7 @@ export interface components { */ objects: string[]; }; - /** - * CollectionElementIdentifier - * @description Base model definition with common configuration used by all derived models. - */ + /** CollectionElementIdentifier */ CollectionElementIdentifier: { /** * Collection Type @@ -2496,10 +2503,7 @@ export interface components { * @enum {string} */ ColletionSourceType: "hda" | "ldda" | "hdca" | "new_collection"; - /** - * CompositeDataElement - * @description Base model definition with common configuration used by all derived models. - */ + /** CompositeDataElement */ CompositeDataElement: { /** Md5 */ MD5?: string; @@ -2584,10 +2588,7 @@ export interface components { /** To posix lines */ to_posix_lines: boolean; }; - /** - * CompositeItems - * @description Base model definition with common configuration used by all derived models. - */ + /** CompositeItems */ CompositeItems: { /** Elements */ elements: ( @@ -2599,10 +2600,7 @@ export interface components { | components["schemas"]["FtpImportElement"] )[]; }; - /** - * ComputeDatasetHashPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** ComputeDatasetHashPayload */ ComputeDatasetHashPayload: { /** * Extra Files Path @@ -2663,10 +2661,7 @@ export interface components { ConvertedDatasetsMap: { [key: string]: string | undefined; }; - /** - * CreateEntryPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateEntryPayload */ CreateEntryPayload: { /** * Name @@ -2680,10 +2675,7 @@ export interface components { */ target: string; }; - /** - * CreateHistoryContentFromStore - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateHistoryContentFromStore */ CreateHistoryContentFromStore: { model_store_format?: components["schemas"]["ModelStoreFormat"]; /** Store Content Uri */ @@ -2691,10 +2683,7 @@ export interface components { /** Store Dict */ store_dict?: Record; }; - /** - * CreateHistoryContentPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateHistoryContentPayload */ CreateHistoryContentPayload: { /** * Collection Type @@ -2768,10 +2757,7 @@ export interface components { */ type?: components["schemas"]["HistoryContentType"]; }; - /** - * CreateHistoryFromStore - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateHistoryFromStore */ CreateHistoryFromStore: { model_store_format?: components["schemas"]["ModelStoreFormat"]; /** Store Content Uri */ @@ -2779,10 +2765,7 @@ export interface components { /** Store Dict */ store_dict?: Record; }; - /** - * CreateLibrariesFromStore - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateLibrariesFromStore */ CreateLibrariesFromStore: { model_store_format?: components["schemas"]["ModelStoreFormat"]; /** Store Content Uri */ @@ -2790,10 +2773,7 @@ export interface components { /** Store Dict */ store_dict?: Record; }; - /** - * CreateLibraryFilePayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateLibraryFilePayload */ CreateLibraryFilePayload: { /** * From HDA ID @@ -2814,10 +2794,7 @@ export interface components { */ ldda_message?: string; }; - /** - * CreateLibraryFolderPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateLibraryFolderPayload */ CreateLibraryFolderPayload: { /** * Description @@ -2831,10 +2808,7 @@ export interface components { */ name: string; }; - /** - * CreateLibraryPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateLibraryPayload */ CreateLibraryPayload: { /** * Description @@ -2870,10 +2844,7 @@ export interface components { */ metrics?: components["schemas"]["Metric"][]; }; - /** - * CreateNewCollectionPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateNewCollectionPayload */ CreateNewCollectionPayload: { /** * Collection Type @@ -2922,10 +2893,7 @@ export interface components { */ name?: string; }; - /** - * CreatePagePayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CreatePagePayload */ CreatePagePayload: { /** * Annotation @@ -2961,10 +2929,7 @@ export interface components { */ title: string; }; - /** - * CreateQuotaParams - * @description Base model definition with common configuration used by all derived models. - */ + /** CreateQuotaParams */ CreateQuotaParams: { /** * Amount @@ -3051,10 +3016,7 @@ export interface components { */ url: string; }; - /** - * CreatedEntryResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** CreatedEntryResponse */ CreatedEntryResponse: { /** * External link @@ -3133,10 +3095,7 @@ export interface components { */ username: string; }; - /** - * CustomBuildCreationPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** CustomBuildCreationPayload */ CustomBuildCreationPayload: { /** * Length type @@ -3160,10 +3119,7 @@ export interface components { * @enum {string} */ CustomBuildLenType: "file" | "fasta" | "text"; - /** - * CustomBuildModel - * @description Base model definition with common configuration used by all derived models. - */ + /** CustomBuildModel */ CustomBuildModel: { /** * Count @@ -3204,10 +3160,7 @@ export interface components { * @description The custom builds associated with the user. */ CustomBuildsCollection: components["schemas"]["CustomBuildModel"][]; - /** - * CustomBuildsMetadataResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** CustomBuildsMetadataResponse */ CustomBuildsMetadataResponse: { /** * Fasta HDAs @@ -3323,10 +3276,7 @@ export interface components { */ populated?: boolean; }; - /** - * DataElementsFromTarget - * @description Base model definition with common configuration used by all derived models. - */ + /** DataElementsFromTarget */ DataElementsFromTarget: { /** * Auto Decompress @@ -3350,10 +3300,7 @@ export interface components { /** Url */ url?: string; }; - /** - * DataElementsTarget - * @description Base model definition with common configuration used by all derived models. - */ + /** DataElementsTarget */ DataElementsTarget: { /** * Auto Decompress @@ -3381,9 +3328,12 @@ export interface components { )[]; }; /** - * DatasetAssociationRoles - * @description Base model definition with common configuration used by all derived models. + * DataItemSourceType + * @description An enumeration. + * @enum {string} */ + DataItemSourceType: "hda" | "ldda" | "hdca" | "dce" | "dc"; + /** DatasetAssociationRoles */ DatasetAssociationRoles: { /** * Access Roles @@ -3404,10 +3354,7 @@ export interface components { */ modify_item_roles?: string[][]; }; - /** - * DatasetCollectionAttributesResult - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetCollectionAttributesResult */ DatasetCollectionAttributesResult: { /** * Dbkey @@ -3450,10 +3397,7 @@ export interface components { * @enum {string} */ DatasetContentType: "meta" | "attr" | "stats" | "data"; - /** - * DatasetErrorMessage - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetErrorMessage */ DatasetErrorMessage: { /** * Dataset @@ -3468,14 +3412,10 @@ export interface components { }; /** * DatasetInheritanceChain - * @description Base model definition with common configuration used by all derived models. * @default [] */ DatasetInheritanceChain: components["schemas"]["DatasetInheritanceChainEntry"][]; - /** - * DatasetInheritanceChainEntry - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetInheritanceChainEntry */ DatasetInheritanceChainEntry: { /** * Dep @@ -3506,10 +3446,7 @@ export interface components { */ manage?: string[]; }; - /** - * DatasetSourceId - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetSourceId */ DatasetSourceId: { /** * ID @@ -3547,10 +3484,7 @@ export interface components { | "failed_metadata" | "deferred" | "discarded"; - /** - * DatasetStorageDetails - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetStorageDetails */ DatasetStorageDetails: { /** * Badges @@ -3603,10 +3537,7 @@ export interface components { */ sources: Record[]; }; - /** - * DatasetSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetSummary */ DatasetSummary: { /** * Create Time @@ -3648,15 +3579,9 @@ export interface components { */ uuid: string; }; - /** - * DatasetSummaryList - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetSummaryList */ DatasetSummaryList: components["schemas"]["DatasetSummary"][]; - /** - * DatasetTextContentDetails - * @description Base model definition with common configuration used by all derived models. - */ + /** DatasetTextContentDetails */ DatasetTextContentDetails: { /** * Item Data @@ -3805,10 +3730,7 @@ export interface components { [key: string]: string | undefined; }; }; - /** - * DefaultQuota - * @description Base model definition with common configuration used by all derived models. - */ + /** DefaultQuota */ DefaultQuota: { /** * Model class @@ -3837,10 +3759,7 @@ export interface components { * @enum {string} */ DefaultQuotaValues: "unregistered" | "registered" | "no"; - /** - * DeleteDatasetBatchPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** DeleteDatasetBatchPayload */ DeleteDatasetBatchPayload: { /** * Datasets @@ -3854,10 +3773,7 @@ export interface components { */ purge?: boolean; }; - /** - * DeleteDatasetBatchResult - * @description Base model definition with common configuration used by all derived models. - */ + /** DeleteDatasetBatchResult */ DeleteDatasetBatchResult: { /** * Errors @@ -3870,10 +3786,7 @@ export interface components { */ success_count: number; }; - /** - * DeleteHistoryContentPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** DeleteHistoryContentPayload */ DeleteHistoryContentPayload: { /** * Purge @@ -3927,10 +3840,15 @@ export interface components { */ purge?: boolean; }; - /** - * DeleteLibraryPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** DeleteJobPayload */ + DeleteJobPayload: { + /** + * Job message + * @description Stop message + */ + message?: string; + }; + /** DeleteLibraryPayload */ DeleteLibraryPayload: { /** * Undelete @@ -3938,10 +3856,7 @@ export interface components { */ undelete: boolean; }; - /** - * DeleteQuotaPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** DeleteQuotaPayload */ DeleteQuotaPayload: { /** * Purge @@ -3950,10 +3865,7 @@ export interface components { */ purge?: boolean; }; - /** - * DeletedCustomBuild - * @description Base model definition with common configuration used by all derived models. - */ + /** DeletedCustomBuild */ DeletedCustomBuild: { /** * Deletion message @@ -3961,10 +3873,7 @@ export interface components { */ message: string; }; - /** - * DetailedUserModel - * @description Base model definition with common configuration used by all derived models. - */ + /** DetailedUserModel */ DetailedUserModel: { /** * Deleted @@ -4073,10 +3982,42 @@ export interface components { * @enum {string} */ ElementsFromType: "archive" | "bagit" | "bagit_archive" | "directory"; - /** - * EncodedDatasetSourceId - * @description Base model definition with common configuration used by all derived models. - */ + /** EncodedDataItemSourceId */ + EncodedDataItemSourceId: { + /** + * ID + * @description The encoded ID of this entity. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Source + * @description The source of this dataset, either `hda`, `ldda`, `hdca`, `dce` or `dc` depending of its origin. + */ + src: components["schemas"]["DataItemSourceType"]; + }; + /** EncodedDatasetJobInfo */ + EncodedDatasetJobInfo: { + /** + * ID + * @description The encoded ID of this entity. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Source + * @description The source of this dataset, either `hda`, `ldda`, `hdca`, `dce` or `dc` depending of its origin. + */ + src: components["schemas"]["DataItemSourceType"]; + /** + * UUID + * Format: uuid4 + * @deprecated + * @description Universal unique identifier for this dataset. + */ + uuid?: string; + }; + /** EncodedDatasetSourceId */ EncodedDatasetSourceId: { /** * ID @@ -4090,6 +4031,21 @@ export interface components { */ src: components["schemas"]["DatasetSourceType"]; }; + /** EncodedHdcaSourceId */ + EncodedHdcaSourceId: { + /** + * ID + * @description The encoded ID of this entity. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Source + * @description The source of this dataset, which in the case of the model can only be `hdca`. + * @enum {string} + */ + src: "hdca"; + }; /** * EncodedHistoryContentItem * @description Identifies a dataset or collection contained in a History. @@ -4108,9 +4064,118 @@ export interface components { id: string; }; /** - * ExportHistoryArchivePayload - * @description Base model definition with common configuration used by all derived models. + * EncodedJobDetails + * @description Basic information about a job. */ + EncodedJobDetails: { + /** + * Command Line + * @description The command line produced by the job. Users can see this value if allowed in the configuration, administrator can always see this value. + */ + command_line?: string; + /** + * Command Version + * @description Tool version indicated during job execution. + */ + command_version: string; + /** + * Copied from Job-ID + * @description Reference to cached job if job execution was cached. + * @example 0123456789ABCDEF + */ + copied_from_job_id?: string; + /** + * Create Time + * Format: date-time + * @description The time and date this item was created. + */ + create_time: string; + /** + * Exit Code + * @description The exit code returned by the tool. Can be unset if the job is not completed yet. + */ + exit_code?: number; + /** + * External ID + * @description The job id used by the external job runner (Condor, Pulsar, etc.)Only administrator can see this value. + */ + external_id?: string; + /** + * Galaxy Version + * @description The (major) version of Galaxy used to create this job. + * @example 21.05 + */ + galaxy_version: string; + /** + * History ID + * @description The encoded ID of the history associated with this item. + * @example 0123456789ABCDEF + */ + history_id?: string; + /** + * ID + * @description The encoded ID of this entity. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Inputs + * @description Dictionary mapping all the tool inputs (by name) to the corresponding data references. + * @default {} + */ + inputs?: { + [key: string]: components["schemas"]["EncodedDatasetJobInfo"] | undefined; + }; + /** + * Model class + * @description The name of the database model class. + * @default Job + * @enum {string} + */ + model_class: "Job"; + /** + * Output collections + * @default {} + */ + output_collections?: { + [key: string]: components["schemas"]["EncodedHdcaSourceId"] | undefined; + }; + /** + * Outputs + * @description Dictionary mapping all the tool outputs (by name) to the corresponding data references. + * @default {} + */ + outputs?: { + [key: string]: components["schemas"]["EncodedDatasetJobInfo"] | undefined; + }; + /** + * Parameters + * @description Object containing all the parameters of the tool associated with this job. The specific parameters depend on the tool itself. + */ + params: Record; + /** + * State + * @description Current state of the job. + */ + state: components["schemas"]["JobState"]; + /** + * Tool ID + * @description Identifier of the tool that generated this job. + */ + tool_id: string; + /** + * Update Time + * Format: date-time + * @description The last time and date this item was updated. + */ + update_time: string; + /** + * User Email + * @description The email of the user that owns this job. Only the owner of the job and administrators can see this value. + */ + user_email?: string; + }; + /** ExportHistoryArchivePayload */ ExportHistoryArchivePayload: { /** * Directory URI @@ -4141,18 +4206,12 @@ export interface components { */ include_hidden?: boolean; }; - /** - * ExportObjectMetadata - * @description Base model definition with common configuration used by all derived models. - */ + /** ExportObjectMetadata */ ExportObjectMetadata: { request_data: components["schemas"]["ExportObjectRequestMetadata"]; result_data?: components["schemas"]["ExportObjectResultMetadata"]; }; - /** - * ExportObjectRequestMetadata - * @description Base model definition with common configuration used by all derived models. - */ + /** ExportObjectRequestMetadata */ ExportObjectRequestMetadata: { /** * Object Id @@ -4170,10 +4229,7 @@ export interface components { */ user_id?: string; }; - /** - * ExportObjectResultMetadata - * @description Base model definition with common configuration used by all derived models. - */ + /** ExportObjectResultMetadata */ ExportObjectResultMetadata: { /** Error */ error?: string; @@ -4220,15 +4276,9 @@ export interface components { */ target_uri: string; }; - /** - * ExportTaskListResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** ExportTaskListResponse */ ExportTaskListResponse: components["schemas"]["ObjectExportTaskResponse"][]; - /** - * ExtraFiles - * @description Base model definition with common configuration used by all derived models. - */ + /** ExtraFiles */ ExtraFiles: { /** * Fuzzy Root @@ -4240,10 +4290,7 @@ export interface components { items_from?: string; src: components["schemas"]["Src"]; }; - /** - * FavoriteObject - * @description Base model definition with common configuration used by all derived models. - */ + /** FavoriteObject */ FavoriteObject: { /** * Object ID @@ -4257,10 +4304,7 @@ export interface components { * @enum {string} */ FavoriteObjectType: "tools"; - /** - * FavoriteObjectsSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** FavoriteObjectsSummary */ FavoriteObjectsSummary: { /** * Favorite tools @@ -4268,10 +4312,7 @@ export interface components { */ tools: string[]; }; - /** - * FetchDataPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** FetchDataPayload */ FetchDataPayload: { /** * History ID @@ -4288,10 +4329,7 @@ export interface components { | components["schemas"]["FtpImportTarget"] )[]; }; - /** - * FileDataElement - * @description Base model definition with common configuration used by all derived models. - */ + /** FileDataElement */ FileDataElement: { /** Md5 */ MD5?: string; @@ -4344,10 +4382,7 @@ export interface components { */ to_posix_lines?: boolean; }; - /** - * FileLibraryFolderItem - * @description Base model definition with common configuration used by all derived models. - */ + /** FileLibraryFolderItem */ FileLibraryFolderItem: { /** Can Manage */ can_manage: boolean; @@ -4406,10 +4441,7 @@ export interface components { */ update_time: string; }; - /** - * FilesSourcePlugin - * @description Base model definition with common configuration used by all derived models. - */ + /** FilesSourcePlugin */ FilesSourcePlugin: { /** * Browsable @@ -4459,7 +4491,6 @@ export interface components { }; /** * FilesSourcePluginList - * @description Base model definition with common configuration used by all derived models. * @default [] * @example [ * { @@ -4477,10 +4508,7 @@ export interface components { | components["schemas"]["BrowsableFilesSourcePlugin"] | components["schemas"]["FilesSourcePlugin"] )[]; - /** - * FolderLibraryFolderItem - * @description Base model definition with common configuration used by all derived models. - */ + /** FolderLibraryFolderItem */ FolderLibraryFolderItem: { /** Can Manage */ can_manage: boolean; @@ -4519,10 +4547,7 @@ export interface components { */ update_time: string; }; - /** - * FtpImportElement - * @description Base model definition with common configuration used by all derived models. - */ + /** FtpImportElement */ FtpImportElement: { /** Md5 */ MD5?: string; @@ -4577,10 +4602,7 @@ export interface components { */ to_posix_lines?: boolean; }; - /** - * FtpImportTarget - * @description Base model definition with common configuration used by all derived models. - */ + /** FtpImportTarget */ FtpImportTarget: { /** * Auto Decompress @@ -4628,10 +4650,7 @@ export interface components { */ name: string; }; - /** - * GroupQuota - * @description Base model definition with common configuration used by all derived models. - */ + /** GroupQuota */ GroupQuota: { /** * Group @@ -4646,15 +4665,9 @@ export interface components { */ model_class: "GroupQuotaAssociation"; }; - /** - * GroupRoleListResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** GroupRoleListResponse */ GroupRoleListResponse: components["schemas"]["GroupRoleResponse"][]; - /** - * GroupRoleResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** GroupRoleResponse */ GroupRoleResponse: { /** * ID @@ -4674,15 +4687,9 @@ export interface components { */ url: string; }; - /** - * GroupUserListResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** GroupUserListResponse */ GroupUserListResponse: components["schemas"]["GroupUserResponse"][]; - /** - * GroupUserResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** GroupUserResponse */ GroupUserResponse: { /** * Email @@ -5465,10 +5472,7 @@ export interface components { * @enum {string} */ HashFunctionNameEnum: "MD5" | "SHA-1" | "SHA-256" | "SHA-512"; - /** - * HdaDestination - * @description Base model definition with common configuration used by all derived models. - */ + /** HdaDestination */ HdaDestination: { /** * Type @@ -5476,10 +5480,7 @@ export interface components { */ type: "hdas"; }; - /** - * HdcaDataItemsFromTarget - * @description Base model definition with common configuration used by all derived models. - */ + /** HdcaDataItemsFromTarget */ HdcaDataItemsFromTarget: { /** * Auto Decompress @@ -5505,10 +5506,7 @@ export interface components { /** Url */ url?: string; }; - /** - * HdcaDataItemsTarget - * @description Base model definition with common configuration used by all derived models. - */ + /** HdcaDataItemsTarget */ HdcaDataItemsTarget: { /** * Auto Decompress @@ -5537,10 +5535,7 @@ export interface components { /** Tags */ tags?: string[]; }; - /** - * HdcaDestination - * @description Base model definition with common configuration used by all derived models. - */ + /** HdcaDestination */ HdcaDestination: { /** * Type @@ -5548,10 +5543,7 @@ export interface components { */ type: "hdca"; }; - /** - * HistoryContentBulkOperationPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** HistoryContentBulkOperationPayload */ HistoryContentBulkOperationPayload: { /** Items */ items?: components["schemas"]["HistoryContentItem"][]; @@ -5562,10 +5554,7 @@ export interface components { | components["schemas"]["ChangeDbkeyOperationParams"] | components["schemas"]["TagOperationParams"]; }; - /** - * HistoryContentBulkOperationResult - * @description Base model definition with common configuration used by all derived models. - */ + /** HistoryContentBulkOperationResult */ HistoryContentBulkOperationResult: { /** Errors */ errors: components["schemas"]["BulkOperationItemError"][]; @@ -5610,10 +5599,7 @@ export interface components { * @enum {string} */ HistoryContentSource: "hda" | "hdca" | "library" | "library_folder" | "new_collection"; - /** - * HistoryContentStats - * @description Base model definition with common configuration used by all derived models. - */ + /** HistoryContentStats */ HistoryContentStats: { /** * Total Matches @@ -5890,10 +5876,7 @@ export interface components { */ text: string; }; - /** - * ImplicitCollectionJobsStateSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** ImplicitCollectionJobsStateSummary */ ImplicitCollectionJobsStateSummary: { /** * ID @@ -5929,10 +5912,7 @@ export interface components { | components["schemas"]["ImportToolDataBundleDatasetSource"] | components["schemas"]["ImportToolDataBundleUriSource"]; }; - /** - * ImportToolDataBundleDatasetSource - * @description Base model definition with common configuration used by all derived models. - */ + /** ImportToolDataBundleDatasetSource */ ImportToolDataBundleDatasetSource: { /** * ID @@ -5947,10 +5927,7 @@ export interface components { */ src: "hda" | "ldda"; }; - /** - * ImportToolDataBundleUriSource - * @description Base model definition with common configuration used by all derived models. - */ + /** ImportToolDataBundleUriSource */ ImportToolDataBundleUriSource: { /** * src @@ -5964,10 +5941,7 @@ export interface components { */ uri: string; }; - /** - * InputArguments - * @description Base model definition with common configuration used by all derived models. - */ + /** InputArguments */ InputArguments: { /** * Database Key @@ -5994,10 +5968,7 @@ export interface components { */ to_posix_lines?: "Yes" | boolean; }; - /** - * InstalledRepositoryToolShedStatus - * @description Base model definition with common configuration used by all derived models. - */ + /** InstalledRepositoryToolShedStatus */ InstalledRepositoryToolShedStatus: { /** * Latest installed revision @@ -6014,10 +5985,7 @@ export interface components { /** Revision Upgrade */ revision_upgrade?: string; }; - /** - * InstalledToolShedRepository - * @description Base model definition with common configuration used by all derived models. - */ + /** InstalledToolShedRepository */ InstalledToolShedRepository: { /** * Changeset revision @@ -6078,10 +6046,7 @@ export interface components { /** Uninstalled */ uninstalled: boolean; }; - /** - * ItemTagsPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** ItemTagsPayload */ ItemTagsPayload: { /** * Item class @@ -6106,15 +6071,55 @@ export interface components { * @enum {string} */ ItemsFromSrc: "url" | "files" | "path" | "ftp_import" | "server_dir"; - /** - * JobExportHistoryArchiveListResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** JobDestinationParams */ + JobDestinationParams: { + /** + * Handler + * @description Name of the process that handled the job. + */ + Handler?: string; + /** + * Runner + * @description Job runner class + */ + Runner?: string; + /** + * Runner Job ID + * @description ID assigned to submitted job by external job running system + */ + "Runner Job ID"?: string; + }; + /** JobDisplayParametersSummary */ + JobDisplayParametersSummary: { + /** + * Has parameter errors + * @description The job has parameter errors + */ + has_parameter_errors: boolean; + /** + * Outputs + * @description Dictionary mapping all the tool outputs (by name) with the corresponding dataset information in a nested format. + */ + outputs: { + [key: string]: components["schemas"]["JobOutput"][] | undefined; + }; + /** + * Parameters + * @description The parameters of the job in a nested format. + */ + parameters: components["schemas"]["JobParameter"][]; + }; + /** JobErrorSummary */ + JobErrorSummary: { + /** + * Error messages + * @description The error messages for the specified job. + */ + messages: string[][]; + }; + /** JobExportHistoryArchiveListResponse */ JobExportHistoryArchiveListResponse: components["schemas"]["JobExportHistoryArchiveModel"][]; - /** - * JobExportHistoryArchiveModel - * @description Base model definition with common configuration used by all derived models. - */ + /** JobExportHistoryArchiveModel */ JobExportHistoryArchiveModel: { /** * Download URL @@ -6173,10 +6178,7 @@ export interface components { */ job_id: string; }; - /** - * JobImportHistoryResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** JobImportHistoryResponse */ JobImportHistoryResponse: { /** * Create Time @@ -6248,6 +6250,32 @@ export interface components { * @enum {string} */ JobIndexViewEnum: "collection" | "admin_job_list"; + /** JobInputAssociation */ + JobInputAssociation: { + /** + * dataset + * @description Reference to the associated item. + */ + dataset: components["schemas"]["EncodedDataItemSourceId"]; + /** + * name + * @description Name of the job input parameter. + */ + name: string; + }; + /** JobInputSummary */ + JobInputSummary: { + /** + * Duplicate inputs + * @description Job has duplicate inputs. + */ + has_duplicate_inputs: boolean; + /** + * Empty inputs + * @description Job has empty inputs. + */ + has_empty_inputs: boolean; + }; /** JobLock */ JobLock: { /** @@ -6256,6 +6284,92 @@ export interface components { */ active: boolean; }; + /** + * JobMetric + * @example { + * "name": "start_epoch", + * "plugin": "core", + * "raw_value": "1614261340.0000000", + * "title": "Job Start Time", + * "value": "2021-02-25 14:55:40" + * } + */ + JobMetric: { + /** + * Name + * @description The name of the metric variable. + */ + name: string; + /** + * Plugin + * @description The instrumenter plugin that generated this metric. + */ + plugin: string; + /** + * Raw Value + * @description The raw value of the metric as a string. + */ + raw_value: string; + /** + * Title + * @description A descriptive title for this metric. + */ + title: string; + /** + * Value + * @description The textual representation of the metric value. + */ + value: string; + }; + /** JobOutput */ + JobOutput: { + /** + * Output label + * @description The output label + */ + label: Record; + /** + * Dataset + * @description The associated dataset. + */ + value: components["schemas"]["EncodedDataItemSourceId"]; + }; + /** JobOutputAssociation */ + JobOutputAssociation: { + /** + * dataset + * @description Reference to the associated item. + */ + dataset: components["schemas"]["EncodedDataItemSourceId"]; + /** + * name + * @description Name of the job output parameter. + */ + name: string; + }; + /** JobParameter */ + JobParameter: { + /** + * Depth + * @description The depth of the job parameter. + */ + depth: number; + /** + * Notes + * @description Notes associated with the job parameter. + */ + notes?: string; + /** + * Text + * @description Text associated with the job parameter. + */ + text: string; + /** + * Value + * @description The values of the job parameter + */ + value: Record; + }; /** * JobSourceType * @description Available types of job sources (model classes) that produce dataset collections. @@ -6283,10 +6397,7 @@ export interface components { | "stop" | "stopped" | "skipped"; - /** - * JobStateSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** JobStateSummary */ JobStateSummary: { /** * ID @@ -6331,10 +6442,7 @@ export interface components { */ value: string; }; - /** - * LegacyLibraryPermissionsPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** LegacyLibraryPermissionsPayload */ LegacyLibraryPermissionsPayload: { /** * Access IDs @@ -6361,10 +6469,7 @@ export interface components { */ LIBRARY_MODIFY_in?: string[] | string; }; - /** - * LibraryAvailablePermissions - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryAvailablePermissions */ LibraryAvailablePermissions: { /** * Page @@ -6387,10 +6492,7 @@ export interface components { */ total: number; }; - /** - * LibraryCurrentPermissions - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryCurrentPermissions */ LibraryCurrentPermissions: { /** * Access Role List @@ -6413,10 +6515,7 @@ export interface components { */ modify_library_role_list: string[][]; }; - /** - * LibraryDestination - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryDestination */ LibraryDestination: { /** * Description @@ -6439,10 +6538,7 @@ export interface components { */ type: "library"; }; - /** - * LibraryFolderContentsIndexResult - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderContentsIndexResult */ LibraryFolderContentsIndexResult: { /** Folder Contents */ folder_contents: ( @@ -6451,10 +6547,7 @@ export interface components { )[]; metadata: components["schemas"]["LibraryFolderMetadata"]; }; - /** - * LibraryFolderCurrentPermissions - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderCurrentPermissions */ LibraryFolderCurrentPermissions: { /** * Add Role List @@ -6472,10 +6565,7 @@ export interface components { */ modify_folder_role_list: string[][]; }; - /** - * LibraryFolderDestination - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderDestination */ LibraryFolderDestination: { /** * Library Folder Id @@ -6488,10 +6578,7 @@ export interface components { */ type: "library_folder"; }; - /** - * LibraryFolderDetails - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderDetails */ LibraryFolderDetails: { /** * Deleted @@ -6558,10 +6645,7 @@ export interface components { */ update_time: string; }; - /** - * LibraryFolderMetadata - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderMetadata */ LibraryFolderMetadata: { /** Can Add Library Item */ can_add_library_item: boolean; @@ -6587,10 +6671,7 @@ export interface components { * @enum {string} */ LibraryFolderPermissionAction: "set_permissions"; - /** - * LibraryFolderPermissionsPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryFolderPermissionsPayload */ LibraryFolderPermissionsPayload: { /** * Action @@ -6616,10 +6697,7 @@ export interface components { */ "modify_ids[]"?: string[] | string; }; - /** - * LibraryLegacySummary - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryLegacySummary */ LibraryLegacySummary: { /** * Create Time @@ -6680,10 +6758,7 @@ export interface components { * @enum {string} */ LibraryPermissionScope: "current" | "available"; - /** - * LibraryPermissionsPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** LibraryPermissionsPayload */ LibraryPermissionsPayload: { /** * Access IDs @@ -6715,10 +6790,7 @@ export interface components { */ "modify_ids[]"?: string[] | string; }; - /** - * LibrarySummary - * @description Base model definition with common configuration used by all derived models. - */ + /** LibrarySummary */ LibrarySummary: { /** * Can User Add @@ -6795,7 +6867,6 @@ export interface components { }; /** * LibrarySummaryList - * @description Base model definition with common configuration used by all derived models. * @default [] */ LibrarySummaryList: components["schemas"]["LibrarySummary"][]; @@ -6909,10 +6980,7 @@ export interface components { * @enum {string} */ MandatoryNotificationCategory: "broadcast"; - /** - * MaterializeDatasetInstanceAPIRequest - * @description Base model definition with common configuration used by all derived models. - */ + /** MaterializeDatasetInstanceAPIRequest */ MaterializeDatasetInstanceAPIRequest: { /** * Content @@ -6929,10 +6997,7 @@ export interface components { */ source: components["schemas"]["DatasetSourceType"]; }; - /** - * MessageNotificationContent - * @description Base model definition with common configuration used by all derived models. - */ + /** MessageNotificationContent */ MessageNotificationContent: { /** * Category @@ -7087,10 +7152,7 @@ export interface components { * @enum {string} */ ModelStoreFormat: "tgz" | "tar" | "tar.gz" | "bag.zip" | "bag.tar" | "bag.tgz" | "rocrate.zip" | "bco.json"; - /** - * NestedElement - * @description Base model definition with common configuration used by all derived models. - */ + /** NestedElement */ NestedElement: { /** Md5 */ MD5?: string; @@ -7151,10 +7213,7 @@ export interface components { */ to_posix_lines?: boolean; }; - /** - * NewSharedItemNotificationContent - * @description Base model definition with common configuration used by all derived models. - */ + /** NewSharedItemNotificationContent */ NewSharedItemNotificationContent: { /** * Category @@ -7308,10 +7367,7 @@ export interface components { */ recipients: components["schemas"]["NotificationRecipients"]; }; - /** - * NotificationCreatedResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** NotificationCreatedResponse */ NotificationCreatedResponse: { /** * Notification @@ -7436,10 +7492,7 @@ export interface components { * @enum {string} */ NotificationVariant: "info" | "warning" | "urgent"; - /** - * NotificationsBatchRequest - * @description Base model definition with common configuration used by all derived models. - */ + /** NotificationsBatchRequest */ NotificationsBatchRequest: { /** * Notification IDs @@ -7458,10 +7511,7 @@ export interface components { */ updated_count: number; }; - /** - * ObjectExportTaskResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** ObjectExportTaskResponse */ ObjectExportTaskResponse: { /** * Create Time @@ -7520,10 +7570,7 @@ export interface components { * @enum {string} */ PageContentFormat: "markdown" | "html"; - /** - * PageDetails - * @description Base model definition with common configuration used by all derived models. - */ + /** PageDetails */ PageDetails: { /** * Content @@ -7620,10 +7667,7 @@ export interface components { */ username: string; }; - /** - * PageSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** PageSummary */ PageSummary: { /** * Create Time @@ -7700,14 +7744,10 @@ export interface components { }; /** * PageSummaryList - * @description Base model definition with common configuration used by all derived models. * @default [] */ PageSummaryList: components["schemas"]["PageSummary"][]; - /** - * PastedDataElement - * @description Base model definition with common configuration used by all derived models. - */ + /** PastedDataElement */ PastedDataElement: { /** Md5 */ MD5?: string; @@ -7765,10 +7805,7 @@ export interface components { */ to_posix_lines?: boolean; }; - /** - * PathDataElement - * @description Base model definition with common configuration used by all derived models. - */ + /** PathDataElement */ PathDataElement: { /** Md5 */ MD5?: string; @@ -7838,10 +7875,7 @@ export interface components { * @enum {string} */ PluginKind: "rfs" | "drs" | "rdm" | "stock"; - /** - * PrepareStoreDownloadPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** PrepareStoreDownloadPayload */ PrepareStoreDownloadPayload: { /** * Bco Merge History Metadata @@ -8017,7 +8051,6 @@ export interface components { }; /** * QuotaSummaryList - * @description Base model definition with common configuration used by all derived models. * @default [] */ QuotaSummaryList: components["schemas"]["QuotaSummary"][]; @@ -8030,10 +8063,7 @@ export interface components { /** Reloaded */ reloaded: string[]; }; - /** - * RemoteDirectory - * @description Base model definition with common configuration used by all derived models. - */ + /** RemoteDirectory */ RemoteDirectory: { /** * Class @@ -8056,10 +8086,7 @@ export interface components { */ uri: string; }; - /** - * RemoteFile - * @description Base model definition with common configuration used by all derived models. - */ + /** RemoteFile */ RemoteFile: { /** * Class @@ -8104,10 +8131,7 @@ export interface components { * @enum {string} */ RemoteFilesFormat: "flat" | "jstree" | "uri"; - /** - * RemoteUserCreationPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** RemoteUserCreationPayload */ RemoteUserCreationPayload: { /** * Email @@ -8115,6 +8139,25 @@ export interface components { */ remote_user_email: string; }; + /** ReportJobErrorPayload */ + ReportJobErrorPayload: { + /** + * History Dataset Association ID + * @description The History Dataset Association ID related to the error. + * @example 0123456789ABCDEF + */ + dataset_id: string; + /** + * Email + * @description Email address for communication with the user. Only required for anonymous users. + */ + email?: string; + /** + * Message + * @description The optional message sent with the error report. + */ + message?: string; + }; /** * RequestDataType * @description Particular pieces of information that can be requested for a dataset. @@ -8135,10 +8178,7 @@ export interface components { * @enum {string} */ Requirement: "logged_in" | "new_history" | "admin"; - /** - * RoleDefinitionModel - * @description Base model definition with common configuration used by all derived models. - */ + /** RoleDefinitionModel */ RoleDefinitionModel: { /** * Description @@ -8161,15 +8201,9 @@ export interface components { */ user_ids?: string[]; }; - /** - * RoleListResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** RoleListResponse */ RoleListResponse: components["schemas"]["RoleModelResponse"][]; - /** - * RoleModelResponse - * @description Base model definition with common configuration used by all derived models. - */ + /** RoleModelResponse */ RoleModelResponse: { /** * Description @@ -8206,10 +8240,25 @@ export interface components { */ url: string; }; - /** - * ServerDirElement - * @description Base model definition with common configuration used by all derived models. - */ + /** SearchJobsPayload */ + SearchJobsPayload: { + /** + * Inputs + * @description The inputs of the job. + */ + inputs: Record; + /** + * State + * @description Current state of the job. + */ + state: components["schemas"]["JobState"]; + /** + * Tool ID + * @description The tool ID related to the job. + */ + tool_id: string; + }; + /** ServerDirElement */ ServerDirElement: { /** Md5 */ MD5?: string; @@ -8354,10 +8403,7 @@ export interface components { */ version: string; }; - /** - * SetSlugPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** SetSlugPayload */ SetSlugPayload: { /** * New Slug @@ -8365,10 +8411,7 @@ export interface components { */ new_slug: string; }; - /** - * ShareWithExtra - * @description Base model definition with common configuration used by all derived models. - */ + /** ShareWithExtra */ ShareWithExtra: { /** * Can Share @@ -8377,10 +8420,7 @@ export interface components { */ can_share?: boolean; }; - /** - * ShareWithPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** ShareWithPayload */ ShareWithPayload: { /** * Share Option @@ -8397,10 +8437,7 @@ export interface components { */ user_ids: (string | string)[]; }; - /** - * ShareWithStatus - * @description Base model definition with common configuration used by all derived models. - */ + /** ShareWithStatus */ ShareWithStatus: { /** * Encoded Email @@ -8462,10 +8499,7 @@ export interface components { * @enum {string} */ SharingOptions: "make_public" | "make_accessible_to_shared" | "no_changes"; - /** - * SharingStatus - * @description Base model definition with common configuration used by all derived models. - */ + /** SharingStatus */ SharingStatus: { /** * Encoded Email @@ -8510,10 +8544,7 @@ export interface components { */ users_shared_with?: components["schemas"]["UserEmail"][]; }; - /** - * ShortTermStoreExportPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** ShortTermStoreExportPayload */ ShortTermStoreExportPayload: { /** Duration */ duration?: number | number; @@ -8552,10 +8583,7 @@ export interface components { * @enum {string} */ Src: "url" | "pasted" | "files" | "path" | "composite" | "ftp_import" | "server_dir"; - /** - * StorageItemCleanupError - * @description Base model definition with common configuration used by all derived models. - */ + /** StorageItemCleanupError */ StorageItemCleanupError: { /** Error */ error: string; @@ -8565,10 +8593,7 @@ export interface components { */ item_id: string; }; - /** - * StorageItemsCleanupResult - * @description Base model definition with common configuration used by all derived models. - */ + /** StorageItemsCleanupResult */ StorageItemsCleanupResult: { /** Errors */ errors: components["schemas"]["StorageItemCleanupError"][]; @@ -8579,10 +8604,7 @@ export interface components { /** Total Item Count */ total_item_count: number; }; - /** - * StoreExportPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** StoreExportPayload */ StoreExportPayload: { /** * Include deleted @@ -8608,10 +8630,7 @@ export interface components { */ model_store_format?: components["schemas"]["ModelStoreFormat"]; }; - /** - * StoredItem - * @description Base model definition with common configuration used by all derived models. - */ + /** StoredItem */ StoredItem: { /** * Id @@ -8637,10 +8656,7 @@ export interface components { * @enum {string} */ StoredItemOrderBy: "name-asc" | "name-dsc" | "size-asc" | "size-dsc" | "update_time-asc" | "update_time-dsc"; - /** - * SuitableConverter - * @description Base model definition with common configuration used by all derived models. - */ + /** SuitableConverter */ SuitableConverter: { /** * Name @@ -8678,10 +8694,7 @@ export interface components { * ] */ TagCollection: string[]; - /** - * TagOperationParams - * @description Base model definition with common configuration used by all derived models. - */ + /** TagOperationParams */ TagOperationParams: { /** Tags */ tags: string[]; @@ -8996,10 +9009,7 @@ export interface components { */ visible?: boolean; }; - /** - * UpdateLibraryFolderPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** UpdateLibraryFolderPayload */ UpdateLibraryFolderPayload: { /** * Description @@ -9012,10 +9022,7 @@ export interface components { */ name?: string; }; - /** - * UpdateLibraryPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** UpdateLibraryPayload */ UpdateLibraryPayload: { /** * Description @@ -9033,10 +9040,7 @@ export interface components { */ synopsis?: string; }; - /** - * UpdateQuotaParams - * @description Base model definition with common configuration used by all derived models. - */ + /** UpdateQuotaParams */ UpdateQuotaParams: { /** * Amount @@ -9104,10 +9108,7 @@ export interface components { [key: string]: components["schemas"]["NotificationCategorySettings"] | undefined; }; }; - /** - * UrlDataElement - * @description Base model definition with common configuration used by all derived models. - */ + /** UrlDataElement */ UrlDataElement: { /** Md5 */ MD5?: string; @@ -9165,10 +9166,7 @@ export interface components { */ url: string; }; - /** - * UserBeaconSetting - * @description Base model definition with common configuration used by all derived models. - */ + /** UserBeaconSetting */ UserBeaconSetting: { /** * Enabled @@ -9176,10 +9174,7 @@ export interface components { */ enabled: boolean; }; - /** - * UserCreationPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** UserCreationPayload */ UserCreationPayload: { /** * Email @@ -9197,10 +9192,7 @@ export interface components { */ username: string; }; - /** - * UserDeletionPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** UserDeletionPayload */ UserDeletionPayload: { /** * Purge user @@ -9208,10 +9200,7 @@ export interface components { */ purge: boolean; }; - /** - * UserEmail - * @description Base model definition with common configuration used by all derived models. - */ + /** UserEmail */ UserEmail: { /** * Email @@ -9405,10 +9394,7 @@ export interface components { */ notification_ids: string[]; }; - /** - * UserQuota - * @description Base model definition with common configuration used by all derived models. - */ + /** UserQuota */ UserQuota: { /** * Model class @@ -9445,15 +9431,9 @@ export interface components { /** Error Type */ type: string; }; - /** - * Visualization - * @description Base model definition with common configuration used by all derived models. - */ + /** Visualization */ Visualization: Record; - /** - * VisualizationSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** VisualizationSummary */ VisualizationSummary: { /** * Annotation @@ -9521,14 +9501,10 @@ export interface components { }; /** * VisualizationSummaryList - * @description Base model definition with common configuration used by all derived models. * @default [] */ VisualizationSummaryList: components["schemas"]["VisualizationSummary"][]; - /** - * WorkflowInvocationStateSummary - * @description Base model definition with common configuration used by all derived models. - */ + /** WorkflowInvocationStateSummary */ WorkflowInvocationStateSummary: { /** * ID @@ -9557,10 +9533,7 @@ export interface components { [key: string]: number | undefined; }; }; - /** - * WriteInvocationStoreToPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** WriteInvocationStoreToPayload */ WriteInvocationStoreToPayload: { /** * Bco Merge History Metadata @@ -9623,10 +9596,7 @@ export interface components { */ target_uri: string; }; - /** - * WriteStoreToPayload - * @description Base model definition with common configuration used by all derived models. - */ + /** WriteStoreToPayload */ WriteStoreToPayload: { /** * Include deleted @@ -10535,6 +10505,77 @@ export interface operations { }; }; }; + get_metrics_api_datasets__dataset_id__metrics_get: { + /** + * Return job metrics for specified job. + * @deprecated + */ + parameters: { + /** @description Whether this dataset belongs to a history (HDA) or a library (LDDA). */ + query?: { + hda_ldda?: components["schemas"]["DatasetSourceType"]; + }; + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the dataset */ + path: { + dataset_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobMetric"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + resolve_parameters_display_api_datasets__dataset_id__parameters_display_get: { + /** + * Resolve parameters as a list for nested display. + * @deprecated + * @description Resolve parameters as a list for nested display. + * This API endpoint is unstable and tied heavily to Galaxy's JS client code, + * this endpoint will change frequently. + */ + parameters: { + /** @description Whether this dataset belongs to a history (HDA) or a library (LDDA). */ + query?: { + hda_ldda?: components["schemas"]["DatasetSourceType"]; + }; + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the dataset */ + path: { + dataset_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobDisplayParametersSummary"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; update_permissions_api_datasets__dataset_id__permissions_put: { /** * Set permissions of the given history dataset to the given role ids. @@ -14615,7 +14656,7 @@ export interface operations { * : The tool ID corresponding to the job. (The tag `t` can be used a short hand alias for this tag to filter on this attribute.) * * `runner` - * : The job runner name used to execte the job. (The tag `r` can be used a short hand alias for this tag to filter on this attribute.) This tag is only available for requests using admin keys and/or sessions. + * : The job runner name used to execute the job. (The tag `r` can be used a short hand alias for this tag to filter on this attribute.) This tag is only available for requests using admin keys and/or sessions. * * `handler` * : The job handler name used to execute the job. (The tag `h` can be used a short hand alias for this tag to filter on this attribute.) This tag is only available for requests using admin keys and/or sessions. @@ -14667,16 +14708,43 @@ export interface operations { }; }; }; - show_api_jobs__id__get: { + search_jobs_api_jobs_search_post: { /** - * Show - * @description Return dictionary containing description of job data - * - * Parameters - * - id: ID of job to return - * - full: Return extra information ? + * Return jobs for current user + * @description This method is designed to scan the list of previously run jobs and find records of jobs that had + * the exact some input parameters and datasets. This can be used to minimize the amount of repeated work, and simply + * recycle the old results. */ + parameters?: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SearchJobsPayload"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["EncodedJobDetails"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + show_job_api_jobs__job_id__get: { + /** Return dictionary containing description of job data. */ parameters: { + /** @description Show extra information. */ query?: { full?: boolean; }; @@ -14684,8 +14752,9 @@ export interface operations { header?: { "run-as"?: string; }; + /** @description The ID of the job */ path: { - id: string; + job_id: string; }; }; responses: { @@ -14703,6 +14772,185 @@ export interface operations { }; }; }; + cancel_job_api_jobs__job_id__delete: { + /** Cancels specified job */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + requestBody?: { + content: { + "application/json": components["schemas"]["DeleteJobPayload"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": boolean; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + check_common_problems_api_jobs__job_id__common_problems_get: { + /** Check inputs and job for common potential problems to aid in error reporting */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobInputSummary"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + destination_params_job_api_jobs__job_id__destination_params_get: { + /** Return destination parameters for specified job. */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobDestinationParams"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + report_error_api_jobs__job_id__error_post: { + /** Submits a bug report via the API. */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReportJobErrorPayload"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobErrorSummary"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_inputs_api_jobs__job_id__inputs_get: { + /** Returns input datasets created by a job. */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobInputAssociation"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_metrics_api_jobs__job_id__metrics_get: { + /** Return job metrics for specified job. */ + parameters: { + /** + * @deprecated + * @description Whether this dataset belongs to a history (HDA) or a library (LDDA). + */ + query?: { + hda_ldda?: components["schemas"]["DatasetSourceType"]; + }; + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobMetric"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; get_token_api_jobs__job_id__oidc_tokens_get: { /** * Get a fresh OIDC token @@ -14738,6 +14986,99 @@ export interface operations { }; }; }; + get_outputs_api_jobs__job_id__outputs_get: { + /** Returns output datasets created by a job. */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobOutputAssociation"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + resolve_parameters_display_api_jobs__job_id__parameters_display_get: { + /** + * Resolve parameters as a list for nested display. + * @description Resolve parameters as a list for nested display. + * This API endpoint is unstable and tied heavily to Galaxy's JS client code, + * this endpoint will change frequently. + */ + parameters: { + /** + * @deprecated + * @description Whether this dataset belongs to a history (HDA) or a library (LDDA). + */ + query?: { + hda_ldda?: components["schemas"]["DatasetSourceType"]; + }; + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobDisplayParametersSummary"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + resume_paused_job_api_jobs__job_id__resume_put: { + /** Resumes a paused job. */ + parameters: { + /** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */ + header?: { + "run-as"?: string; + }; + /** @description The ID of the job */ + path: { + job_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["JobOutputAssociation"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; index_api_libraries_get: { /** * Returns a list of summary data for all libraries. diff --git a/lib/galaxy/managers/jobs.py b/lib/galaxy/managers/jobs.py index fcb09f1b9a84..a1ac6728591a 100644 --- a/lib/galaxy/managers/jobs.py +++ b/lib/galaxy/managers/jobs.py @@ -880,6 +880,8 @@ def summarize_job_parameters(trans, job): Precondition: the caller has verified the job is accessible to the user represented by the trans parameter. """ + # More client logic here than is ideal but it is hard to reason about + # tool parameter types on the client relative to the server. def inputs_recursive(input_params, param_values, depth=1, upgrade_messages=None): if upgrade_messages is None: diff --git a/lib/galaxy/schema/jobs.py b/lib/galaxy/schema/jobs.py new file mode 100644 index 000000000000..a69943343cdd --- /dev/null +++ b/lib/galaxy/schema/jobs.py @@ -0,0 +1,233 @@ +import json +from typing import ( + Any, + Dict, + List, + Optional, +) + +from pydantic import ( + Extra, + Field, + Required, + UUID4, + validator, +) +from typing_extensions import Literal + +from galaxy.schema.fields import ( + DecodedDatabaseIdField, + EncodedDatabaseIdField, +) +from galaxy.schema.schema import ( + DataItemSourceType, + EncodedDataItemSourceId, + EntityIdField, + JobState, + JobSummary, + Model, +) + + +class JobInputSummary(Model): + has_empty_inputs: bool = Field( + default=Required, + title="Empty inputs", + description="Job has empty inputs.", + ) + has_duplicate_inputs: bool = Field( + default=Required, + title="Duplicate inputs", + description="Job has duplicate inputs.", + ) + + +# TODO: Use Tuple again when `make update-client-api-schema` supports them +class JobErrorSummary(Model): + # messages: List[Union[Tuple[str, str], List[str]]] + messages: List[List[str]] = Field( + default=Required, + title="Error messages", + description="The error messages for the specified job.", + ) + + +class JobAssociation(Model): + name: str = Field( + default=Required, + title="name", + description="Name of the job parameter.", + ) + dataset: EncodedDataItemSourceId = Field( + default=Required, + title="dataset", + description="Reference to the associated item.", + ) + + +class JobInputAssociation(JobAssociation): + name: str = Field( + default=Required, + title="name", + description="Name of the job input parameter.", + ) + + +class JobOutputAssociation(JobAssociation): + name: str = Field( + default=Required, + title="name", + description="Name of the job output parameter.", + ) + + +class ReportJobErrorPayload(Model): + dataset_id: DecodedDatabaseIdField = Field( + default=Required, + title="History Dataset Association ID", + description="The History Dataset Association ID related to the error.", + ) + email: Optional[str] = Field( + default=None, + title="Email", + description="Email address for communication with the user. Only required for anonymous users.", + ) + message: Optional[str] = Field( + default=None, + title="Message", + description="The optional message sent with the error report.", + ) + + +class SearchJobsPayload(Model): + tool_id: str = Field( + default=Required, + title="Tool ID", + description="The tool ID related to the job.", + ) + inputs: Dict[str, Any] = Field( + default=Required, + title="Inputs", + description="The inputs of the job.", + ) + state: JobState = Field( + default=Required, + title="State", + description="Current state of the job.", + ) + + @validator("inputs", pre=True) + def decode_json(cls, v): + if isinstance(v, str): + return json.loads(v) + return v + + class Config: + extra = Extra.allow # This is used for items named file_ and __file_ + + +class DeleteJobPayload(Model): + message: Optional[str] = Field( + default=None, + title="Job message", + description="Stop message", + ) + + +class SrcItem(Model): + src: DataItemSourceType + + +class EncodedHdcaSourceId(SrcItem): + id: EncodedDatabaseIdField = EntityIdField + src: Literal[DataItemSourceType.hdca] = Field( + default=Required, + title="Source", + description="The source of this dataset, which in the case of the model can only be `hdca`.", + ) + + +class EncodedDatasetJobInfo(EncodedDataItemSourceId): + uuid: Optional[UUID4] = Field( + default=None, + deprecated=True, + title="UUID", + description="Universal unique identifier for this dataset.", + ) + + +class EncodedJobDetails(JobSummary): + command_version: str = Field( + ..., + title="Command Version", + description="Tool version indicated during job execution.", + ) + params: Any = Field( + ..., + title="Parameters", + description=( + "Object containing all the parameters of the tool associated with this job. " + "The specific parameters depend on the tool itself." + ), + ) + inputs: Dict[str, EncodedDatasetJobInfo] = Field( + {}, + title="Inputs", + description="Dictionary mapping all the tool inputs (by name) to the corresponding data references.", + ) + outputs: Dict[str, EncodedDatasetJobInfo] = Field( + {}, + title="Outputs", + description="Dictionary mapping all the tool outputs (by name) to the corresponding data references.", + ) + copied_from_job_id: Optional[EncodedDatabaseIdField] = Field( + default=None, title="Copied from Job-ID", description="Reference to cached job if job execution was cached." + ) + output_collections: Dict[str, EncodedHdcaSourceId] = Field(default={}, title="Output collections", description="") + + +class JobDestinationParams(Model): + runner: Optional[str] = Field(None, title="Runner", description="Job runner class", alias="Runner") + runner_job_id: Optional[str] = Field( + None, + title="Runner Job ID", + description="ID assigned to submitted job by external job running system", + alias="Runner Job ID", + ) + handler: Optional[str] = Field( + None, title="Handler", description="Name of the process that handled the job.", alias="Handler" + ) + + +class JobOutput(Model): + label: Any = Field(default=Required, title="Output label", description="The output label") # check if this is true + value: EncodedDataItemSourceId = Field(default=Required, title="Dataset", description="The associated dataset.") + + +class JobParameter(Model): + text: str = Field( + default=Required, + title="Text", + description="Text associated with the job parameter.", + ) + depth: int = Field( + default=Required, + title="Depth", + description="The depth of the job parameter.", + ) + value: Any = Field(default=Required, title="Value", description="The values of the job parameter") + notes: Optional[str] = Field(default=None, title="Notes", description="Notes associated with the job parameter.") + + +class JobDisplayParametersSummary(Model): + parameters: List[JobParameter] = Field( + default=Required, title="Parameters", description="The parameters of the job in a nested format." + ) + has_parameter_errors: bool = Field( + default=Required, title="Has parameter errors", description="The job has parameter errors" + ) + outputs: Dict[str, List[JobOutput]] = Field( + default=Required, + title="Outputs", + description="Dictionary mapping all the tool outputs (by name) with the corresponding dataset information in a nested format.", + ) diff --git a/lib/galaxy/schema/schema.py b/lib/galaxy/schema/schema.py index 417c69f83cf0..6920fe5dbb94 100644 --- a/lib/galaxy/schema/schema.py +++ b/lib/galaxy/schema/schema.py @@ -257,8 +257,6 @@ class DatasetCollectionPopulatedState(str, Enum): class Model(BaseModel): - """Base model definition with common configuration used by all derived models.""" - class Config: use_enum_values = True # when using .dict() allow_population_by_field_name = True @@ -475,6 +473,14 @@ class DatasetSourceType(str, Enum): ldda = "ldda" +class DataItemSourceType(str, Enum): + hda = "hda" + ldda = "ldda" + hdca = "hdca" + dce = "dce" + dc = "dc" + + class ColletionSourceType(str, Enum): hda = "hda" ldda = "ldda" @@ -1821,18 +1827,18 @@ class JobIdResponse(Model): class JobBaseModel(Model): - id: DecodedDatabaseIdField = EntityIdField + id: EncodedDatabaseIdField = EntityIdField + history_id: Optional[EncodedDatabaseIdField] = Field( + None, + title="History ID", + description="The encoded ID of the history associated with this item.", + ) model_class: JOB_MODEL_CLASS = ModelClassField(JOB_MODEL_CLASS) tool_id: str = Field( ..., title="Tool ID", description="Identifier of the tool that generated this job.", ) - history_id: Optional[DecodedDatabaseIdField] = Field( - None, - title="History ID", - description="The encoded ID of the history associated with this item.", - ) state: JobState = Field( ..., title="State", @@ -1925,6 +1931,15 @@ class EncodedDatasetSourceId(DatasetSourceIdBase): id: EncodedDatabaseIdField = EntityIdField +class EncodedDataItemSourceId(Model): + id: EncodedDatabaseIdField = EntityIdField + src: DataItemSourceType = Field( + ..., + title="Source", + description="The source of this dataset, either `hda`, `ldda`, `hdca`, `dce` or `dc` depending of its origin.", + ) + + class DatasetJobInfo(DatasetSourceId): uuid: UUID4 = UuidField diff --git a/lib/galaxy/security/idencoding.py b/lib/galaxy/security/idencoding.py index 9c0b10ce2a20..e1eca5d2a314 100644 --- a/lib/galaxy/security/idencoding.py +++ b/lib/galaxy/security/idencoding.py @@ -35,9 +35,11 @@ def __init__(self, **config): per_kind_id_secret_base = config.get("per_kind_id_secret_base", self.id_secret) self.id_ciphers_for_kind = _cipher_cache(per_kind_id_secret_base) - def encode_id(self, obj_id, kind=None): + def encode_id(self, obj_id, kind=None, strict_integer=False): if obj_id is None: raise galaxy.exceptions.MalformedId("Attempted to encode None id") + if strict_integer and not isinstance(obj_id, int): + raise galaxy.exceptions.MalformedId("Attempted to encode id that is not an integer") id_cipher = self.__id_cipher(kind) # Convert to bytes s = smart_str(obj_id) diff --git a/lib/galaxy/webapps/galaxy/api/jobs.py b/lib/galaxy/webapps/galaxy/api/jobs.py index 72a565b05ccd..bd19370dd6ae 100644 --- a/lib/galaxy/webapps/galaxy/api/jobs.py +++ b/lib/galaxy/webapps/galaxy/api/jobs.py @@ -18,35 +18,45 @@ ) from fastapi import ( + Body, Depends, + Path, Query, ) +from pydantic import Required +from typing_extensions import Annotated -from galaxy import ( - exceptions, - model, -) -from galaxy.managers import hdas +from galaxy import exceptions from galaxy.managers.context import ( ProvidesHistoryContext, ProvidesUserContext, ) from galaxy.managers.jobs import ( - JobLock, JobManager, - JobSearch, summarize_destination_params, summarize_job_metrics, summarize_job_parameters, ) from galaxy.schema.fields import DecodedDatabaseIdField -from galaxy.schema.schema import JobIndexSortByEnum -from galaxy.schema.types import OffsetNaiveDatetime -from galaxy.web import ( - expose_api, - expose_api_anonymous, - require_admin, +from galaxy.schema.jobs import ( + DeleteJobPayload, + EncodedJobDetails, + JobDestinationParams, + JobDisplayParametersSummary, + JobErrorSummary, + JobInputAssociation, + JobInputSummary, + JobOutputAssociation, + ReportJobErrorPayload, + SearchJobsPayload, ) +from galaxy.schema.schema import ( + DatasetSourceType, + JobIndexSortByEnum, + JobMetric, +) +from galaxy.schema.types import OffsetNaiveDatetime +from galaxy.web import expose_api_anonymous from galaxy.webapps.base.controller import UsesVisualizationMixin from galaxy.webapps.galaxy.api import ( BaseGalaxyAPIController, @@ -157,7 +167,7 @@ query_tags = [ IndexQueryTag("user", "The user email of the user that executed the Job.", "u"), IndexQueryTag("tool_id", "The tool ID corresponding to the job.", "t"), - IndexQueryTag("runner", "The job runner name used to execte the job.", "r", admin_only=True), + IndexQueryTag("runner", "The job runner name used to execute the job.", "r", admin_only=True), IndexQueryTag("handler", "The job handler name used to execute the job.", "h", admin_only=True), ] @@ -167,27 +177,30 @@ free_text_fields=["user", "tool", "handler", "runner"], ) +FullShowQueryParam: Optional[bool] = Query(title="Full show", description="Show extra information.") +DeprecatedHdaLddaQueryParam: Optional[DatasetSourceType] = Query( + deprecated=True, + title="HDA or LDDA", + description="Whether this dataset belongs to a history (HDA) or a library (LDDA).", +) +HdaLddaQueryParam: DatasetSourceType = Query( + title="HDA or LDDA", + description="Whether this dataset belongs to a history (HDA) or a library (LDDA).", +) + + +JobIdPathParam: DecodedDatabaseIdField = Path(title="Job ID", description="The ID of the job") +DatasetIdPathParam: DecodedDatabaseIdField = Path(title="Dataset ID", description="The ID of the dataset") + +ReportErrorBody = Body(default=Required, title="Report error", description="The values to report an Error") +SearchJobBody = Body(default=Required, title="Search job", description="The values to search an Job") +DeleteJobBody = Body(title="Delete/cancel job", description="The values to delete/cancel a job") + @router.cbv class FastAPIJobs: service: JobsService = depends(JobsService) - @router.get("/api/jobs/{id}") - def show( - self, - id: DecodedDatabaseIdField, - trans: ProvidesUserContext = DependsOnTrans, - full: Optional[bool] = False, - ) -> Dict[str, Any]: - """ - Return dictionary containing description of job data - - Parameters - - id: ID of job to return - - full: Return extra information ? - """ - return self.service.show(trans, id, bool(full)) - @router.get("/api/jobs") def index( self, @@ -227,19 +240,17 @@ def index( ) return self.service.index(trans, payload) - -class JobController(BaseGalaxyAPIController, UsesVisualizationMixin): - job_manager = depends(JobManager) - job_search = depends(JobSearch) - hda_manager = depends(hdas.HDAManager) - - @expose_api - def common_problems(self, trans: ProvidesUserContext, id, **kwd): - """ - * GET /api/jobs/{id}/common_problems - check inputs and job for common potential problems to aid in error reporting - """ - job = self.__get_job(trans, id) + @router.get( + "/api/jobs/{job_id}/common_problems", + name="check_common_problems", + summary="Check inputs and job for common potential problems to aid in error reporting", + ) + def common_problems( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> JobInputSummary: + job = self.service.get_job(trans=trans, job_id=job_id) seen_ids = set() has_empty_inputs = False has_duplicate_inputs = False @@ -257,234 +268,205 @@ def common_problems(self, trans: ProvidesUserContext, id, **kwd): # TODO: check percent of failing jobs around a window on job.update_time for handler - report if high. # TODO: check percent of failing jobs around a window on job.update_time for destination_id - report if high. # TODO: sniff inputs (add flag to allow checking files?) - return {"has_empty_inputs": has_empty_inputs, "has_duplicate_inputs": has_duplicate_inputs} - - @expose_api - def inputs(self, trans: ProvidesUserContext, id, **kwd) -> List[dict]: - """ - GET /api/jobs/{id}/inputs - - returns input datasets created by job - - :type id: string - :param id: Encoded job id - - :rtype: list of dicts - :returns: list of dictionaries containing input dataset associations - """ - job = self.__get_job(trans, id) - return self.__dictify_associations(trans, job.input_datasets, job.input_library_datasets) - - @expose_api - def outputs(self, trans: ProvidesUserContext, id, **kwd) -> List[dict]: - """ - outputs( trans, id ) - * GET /api/jobs/{id}/outputs - returns output datasets created by job - - :type id: string - :param id: Encoded job id - - :rtype: list of dicts - :returns: list of dictionaries containing output dataset associations - """ - job = self.__get_job(trans, id) - return self.__dictify_associations(trans, job.output_datasets, job.output_library_datasets) - - @expose_api - def delete(self, trans: ProvidesUserContext, id, **kwd): - """ - delete( trans, id ) - * Delete /api/jobs/{id} - cancels specified job - - :type id: string - :param id: Encoded job id - :type message: string - :param message: Stop message. - """ - payload = kwd.get("payload") or {} - job = self.__get_job(trans, id) - message = payload.get("message", None) - return self.job_manager.stop(job, message=message) - - @expose_api - def resume(self, trans: ProvidesUserContext, id, **kwd) -> List[dict]: - """ - * PUT /api/jobs/{id}/resume - Resumes a paused job - - :type id: string - :param id: Encoded job id - - :rtype: list of dicts - :returns: list of dictionaries containing output dataset associations - """ - job = self.__get_job(trans, id) + return JobInputSummary(has_empty_inputs=has_empty_inputs, has_duplicate_inputs=has_duplicate_inputs) + + @router.put( + "/api/jobs/{job_id}/resume", + name="resume_paused_job", + summary="Resumes a paused job.", + ) + def resume( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> List[JobOutputAssociation]: + job = self.service.get_job(trans, job_id=job_id) if not job: raise exceptions.ObjectNotFound("Could not access job with the given id") if job.state == job.states.PAUSED: job.resume() else: exceptions.RequestParameterInvalidException(f"Job with id '{job.tool_id}' is not paused") - return self.__dictify_associations(trans, job.output_datasets, job.output_library_datasets) - - @expose_api_anonymous - def metrics(self, trans: ProvidesUserContext, **kwd): - """ - * GET /api/jobs/{job_id}/metrics - * GET /api/datasets/{dataset_id}/metrics - Return job metrics for specified job. Job accessibility checks are slightly - different than dataset checks, so both methods are available. - - :type job_id: string - :param job_id: Encoded job id - - :type dataset_id: string - :param dataset_id: Encoded HDA or LDDA id - - :type hda_ldda: string - :param hda_ldda: hda if dataset_id is an HDA id (default), ldda if - it is an ldda id. - - :rtype: list - :returns: list containing job metrics - """ - job = self.__get_job(trans, **kwd) - return summarize_job_metrics(trans, job) - - @require_admin - @expose_api - def destination_params(self, trans: ProvidesUserContext, **kwd): - """ - * GET /api/jobs/{job_id}/destination_params - Return destination parameters for specified job. - - :type job_id: string - :param job_id: Encoded job id - - :rtype: list - :returns: list containing job destination parameters - """ - job = self.__get_job(trans, **kwd) - return summarize_destination_params(trans, job) - - @expose_api_anonymous - def parameters_display(self, trans: ProvidesUserContext, **kwd): + associations = self.service.dictify_associations(trans, job.output_datasets, job.output_library_datasets) + output_associations = [] + for association in associations: + output_associations.append(JobOutputAssociation(name=association.name, dataset=association.dataset)) + return output_associations + + @router.post( + "/api/jobs/{job_id}/error", + name="report_error", + summary="Submits a bug report via the API.", + ) + def error( + self, + payload: Annotated[ReportJobErrorPayload, ReportErrorBody], + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> JobErrorSummary: + # Get dataset on which this error was triggered + dataset_id = payload.dataset_id + dataset = self.service.hda_manager.get_accessible(id=dataset_id, user=trans.user) + # Get job + job = self.service.get_job(trans, job_id) + if dataset.creating_job.id != job.id: + raise exceptions.RequestParameterInvalidException("dataset_id was not created by job_id") + tool = trans.app.toolbox.get_tool(job.tool_id, tool_version=job.tool_version) or None + email = payload.email + if not email and not trans.anonymous: + email = trans.user.email + messages = trans.app.error_reports.default_error_plugin.submit_report( + dataset=dataset, + job=job, + tool=tool, + user_submission=True, + user=trans.user, + email=email, + message=payload.message, + ) + return JobErrorSummary(messages=messages) + + @router.get( + "/api/jobs/{job_id}/inputs", + name="get_inputs", + summary="Returns input datasets created by a job.", + ) + def inputs( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> List[JobInputAssociation]: + job = self.service.get_job(trans=trans, job_id=job_id) + associations = self.service.dictify_associations(trans, job.input_datasets, job.input_library_datasets) + input_associations = [] + for association in associations: + input_associations.append(JobInputAssociation(name=association.name, dataset=association.dataset)) + return input_associations + + @router.get( + "/api/jobs/{job_id}/outputs", + name="get_outputs", + summary="Returns output datasets created by a job.", + ) + def outputs( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> List[JobOutputAssociation]: + job = self.service.get_job(trans=trans, job_id=job_id) + associations = self.service.dictify_associations(trans, job.output_datasets, job.output_library_datasets) + output_associations = [] + for association in associations: + output_associations.append(JobOutputAssociation(name=association.name, dataset=association.dataset)) + return output_associations + + @router.get( + "/api/jobs/{job_id}/parameters_display", + name="resolve_parameters_display", + summary="Resolve parameters as a list for nested display.", + ) + def parameters_display_by_job( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + hda_ldda: Annotated[Optional[DatasetSourceType], DeprecatedHdaLddaQueryParam] = DatasetSourceType.hda, + trans: ProvidesUserContext = DependsOnTrans, + ) -> JobDisplayParametersSummary: """ - * GET /api/jobs/{job_id}/parameters_display - * GET /api/datasets/{dataset_id}/parameters_display - - Resolve parameters as a list for nested display. More client logic - here than is ideal but it is hard to reason about tool parameter - types on the client relative to the server. Job accessibility checks - are slightly different than dataset checks, so both methods are - available. - - This API endpoint is unstable and tied heavily to Galaxy's JS client code, - this endpoint will change frequently. - - :type job_id: string - :param job_id: Encoded job id - - :type dataset_id: string - :param dataset_id: Encoded HDA or LDDA id - - :type hda_ldda: string - :param hda_ldda: hda if dataset_id is an HDA id (default), ldda if - it is an ldda id. - - :rtype: list - :returns: job parameters for for display + Resolve parameters as a list for nested display. + This API endpoint is unstable and tied heavily to Galaxy's JS client code, + this endpoint will change frequently. """ - job = self.__get_job(trans, **kwd) + hda_ldda_str = hda_ldda or "hda" + job = self.service.get_job(trans, job_id=job_id, hda_ldda=hda_ldda_str) return summarize_job_parameters(trans, job) - @expose_api_anonymous - def build_for_rerun(self, trans: ProvidesHistoryContext, id, **kwd): + @router.get( + "/api/datasets/{dataset_id}/parameters_display", + name="resolve_parameters_display", + summary="Resolve parameters as a list for nested display.", + deprecated=True, + ) + def parameters_display_by_dataset( + self, + dataset_id: Annotated[DecodedDatabaseIdField, DatasetIdPathParam], + hda_ldda: Annotated[DatasetSourceType, HdaLddaQueryParam] = DatasetSourceType.hda, + trans: ProvidesUserContext = DependsOnTrans, + ) -> JobDisplayParametersSummary: """ - * GET /api/jobs/{id}/build_for_rerun - returns a tool input/param template prepopulated with this job's - information, suitable for rerunning or rendering parameters of the - job. - - :type id: string - :param id: Encoded job id - - :rtype: dictionary - :returns: dictionary containing output dataset associations + Resolve parameters as a list for nested display. + This API endpoint is unstable and tied heavily to Galaxy's JS client code, + this endpoint will change frequently. """ + job = self.service.get_job(trans, dataset_id=dataset_id, hda_ldda=hda_ldda) + return summarize_job_parameters(trans, job) - job = self.__get_job(trans, id) - if not job: - raise exceptions.ObjectNotFound("Could not access job with the given id") - tool = self.app.toolbox.get_tool(job.tool_id, kwd.get("tool_version") or job.tool_version) - if tool is None: - raise exceptions.ObjectNotFound("Requested tool not found") - if not tool.is_workflow_compatible: - raise exceptions.ConfigDoesNotAllowException(f"Tool '{job.tool_id}' cannot be rerun.") - return tool.to_json(trans, {}, job=job) - - def __dictify_associations(self, trans, *association_lists) -> List[dict]: - rval: List[dict] = [] - for association_list in association_lists: - rval.extend(self.__dictify_association(trans, a) for a in association_list) - return rval - - def __dictify_association(self, trans, job_dataset_association) -> dict: - dataset_dict = None - dataset = job_dataset_association.dataset - if dataset: - if isinstance(dataset, model.HistoryDatasetAssociation): - dataset_dict = dict(src="hda", id=trans.security.encode_id(dataset.id)) - else: - dataset_dict = dict(src="ldda", id=trans.security.encode_id(dataset.id)) - return dict(name=job_dataset_association.name, dataset=dataset_dict) - - def __get_job(self, trans, job_id=None, dataset_id=None, **kwd): - if job_id is not None: - decoded_job_id = self.decode_id(job_id) - return self.job_manager.get_accessible_job(trans, decoded_job_id) - else: - hda_ldda = kwd.get("hda_ldda", "hda") - # Following checks dataset accessible - dataset_instance = self.get_hda_or_ldda(trans, hda_ldda=hda_ldda, dataset_id=dataset_id) - return dataset_instance.creating_job - - @expose_api - def create(self, trans: ProvidesUserContext, payload, **kwd): - """See the create method in tools.py in order to submit a job.""" - raise exceptions.NotImplemented("Please POST to /api/tools instead.") - - @expose_api - def search(self, trans: ProvidesHistoryContext, payload: dict, **kwd): + @router.get( + "/api/jobs/{job_id}/metrics", + name="get_metrics", + summary="Return job metrics for specified job.", + ) + def metrics_by_job( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + hda_ldda: Annotated[Optional[DatasetSourceType], DeprecatedHdaLddaQueryParam] = DatasetSourceType.hda, + trans: ProvidesUserContext = DependsOnTrans, + ) -> List[Optional[JobMetric]]: + hda_ldda_str = hda_ldda or "hda" + job = self.service.get_job(trans, job_id=job_id, hda_ldda=hda_ldda_str) + return [JobMetric(**metric) for metric in summarize_job_metrics(trans, job)] + + @router.get( + "/api/datasets/{dataset_id}/metrics", + name="get_metrics", + summary="Return job metrics for specified job.", + deprecated=True, + ) + def metrics_by_dataset( + self, + dataset_id: Annotated[DecodedDatabaseIdField, DatasetIdPathParam], + hda_ldda: Annotated[DatasetSourceType, HdaLddaQueryParam] = DatasetSourceType.hda, + trans: ProvidesUserContext = DependsOnTrans, + ) -> List[Optional[JobMetric]]: + job = self.service.get_job(trans, dataset_id=dataset_id, hda_ldda=hda_ldda) + return [JobMetric(**metric) for metric in summarize_job_metrics(trans, job)] + + @router.get( + "/api/jobs/{job_id}/destination_params", + name="destination_params_job", + summary="Return destination parameters for specified job.", + require_admin=True, + ) + def destination_params( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + ) -> JobDestinationParams: + job = self.service.get_job(trans, job_id=job_id) + return JobDestinationParams(**summarize_destination_params(trans, job)) + + @router.post( + "/api/jobs/search", + name="search_jobs", + summary="Return jobs for current user", + ) + def search( + self, + payload: Annotated[SearchJobsPayload, SearchJobBody], + trans: ProvidesHistoryContext = DependsOnTrans, + ) -> List[EncodedJobDetails]: """ - search( trans, payload ) - * POST /api/jobs/search: - return jobs for current user - - :type payload: dict - :param payload: Dictionary containing description of requested job. This is in the same format as - a request to POST /apt/tools would take to initiate a job - - :rtype: list - :returns: list of dictionaries containing summary job information of the jobs that match the requested job run - This method is designed to scan the list of previously run jobs and find records of jobs that had the exact some input parameters and datasets. This can be used to minimize the amount of repeated work, and simply recycle the old results. """ - tool_id = payload.get("tool_id") - if tool_id is None: - raise exceptions.RequestParameterMissingException("No tool id") + tool_id = payload.tool_id + tool = trans.app.toolbox.get_tool(tool_id) if tool is None: raise exceptions.ObjectNotFound("Requested tool not found") - if "inputs" not in payload: - raise exceptions.RequestParameterMissingException("No inputs defined") - inputs = payload.get("inputs", {}) + inputs = payload.inputs # Find files coming in as multipart file data and add to inputs. - for k, v in payload.items(): + for k, v in payload.__annotations__.items(): if k.startswith("files_") or k.startswith("__files_"): inputs[k] = v request_context = WorkRequestContext(app=trans.app, user=trans.user, history=trans.history) @@ -493,77 +475,87 @@ def search(self, trans: ProvidesHistoryContext, payload: dict, **kwd): ) if any(all_errors): return [] - params_dump = [tool.params_to_strings(param, self.app, nested=True) for param in all_params] + params_dump = [tool.params_to_strings(param, trans.app, nested=True) for param in all_params] jobs = [] for param_dump, param in zip(params_dump, all_params): - job = self.job_search.by_tool_input( + job = self.service.job_search.by_tool_input( trans=trans, tool_id=tool_id, tool_version=tool.version, param=param, param_dump=param_dump, - job_state=payload.get("state"), + job_state=payload.state, ) if job: jobs.append(job) - return [self.encode_all_ids(trans, single_job.to_dict("element"), True) for single_job in jobs] + return [EncodedJobDetails(**single_job.to_dict("element")) for single_job in jobs] + + @router.get( + "/api/jobs/{job_id}", + name="show_job", + summary="Return dictionary containing description of job data.", + ) + def show( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + full: Annotated[Optional[bool], FullShowQueryParam] = False, + trans: ProvidesUserContext = DependsOnTrans, + ) -> Dict[str, Any]: + return self.service.show(trans, job_id, bool(full)) + + @router.delete( + "/api/jobs/{job_id}", + name="cancel_job", + summary="Cancels specified job", + ) + def delete( + self, + job_id: Annotated[DecodedDatabaseIdField, JobIdPathParam], + trans: ProvidesUserContext = DependsOnTrans, + payload: Annotated[Optional[DeleteJobPayload], DeleteJobBody] = None, + ) -> bool: + job = self.service.get_job(trans=trans, job_id=job_id) + if payload: + message = payload.message + else: + message = None + return self.service.job_manager.stop(job, message=message) + + +class JobController(BaseGalaxyAPIController, UsesVisualizationMixin): + job_manager = depends(JobManager) @expose_api_anonymous - def error(self, trans: ProvidesUserContext, id, payload, **kwd): + def build_for_rerun(self, trans: ProvidesHistoryContext, id, **kwd): """ - error( trans, id ) - * POST /api/jobs/{id}/error - submits a bug report via the API. + * GET /api/jobs/{id}/build_for_rerun + returns a tool input/param template prepopulated with this job's + information, suitable for rerunning or rendering parameters of the + job. :type id: string :param id: Encoded job id :rtype: dictionary - :returns: dictionary containing information regarding where the error report was sent. + :returns: dictionary containing output dataset associations """ - # Get dataset on which this error was triggered - dataset_id = payload.get("dataset_id") - if not dataset_id: - raise exceptions.RequestParameterMissingException("No dataset_id") - decoded_dataset_id = self.decode_id(dataset_id) - dataset = self.hda_manager.get_accessible(decoded_dataset_id, trans.user) - # Get job job = self.__get_job(trans, id) - if dataset.creating_job.id != job.id: - raise exceptions.RequestParameterInvalidException("dataset_id was not created by job_id") - tool = trans.app.toolbox.get_tool(job.tool_id, tool_version=job.tool_version) or None - email = payload.get("email") - if not email and not trans.anonymous: - email = trans.user.email - messages = trans.app.error_reports.default_error_plugin.submit_report( - dataset=dataset, - job=job, - tool=tool, - user_submission=True, - user=trans.user, - email=email, - message=payload.get("message"), - ) - - return {"messages": messages} - - @require_admin - @expose_api - def show_job_lock(self, trans: ProvidesUserContext, **kwd): - """ - * GET /api/job_lock - return boolean indicating if job lock active. - """ - return self.job_manager.job_lock() + if not job: + raise exceptions.ObjectNotFound("Could not access job with the given id") + tool = self.app.toolbox.get_tool(job.tool_id, kwd.get("tool_version") or job.tool_version) + if tool is None: + raise exceptions.ObjectNotFound("Requested tool not found") + if not tool.is_workflow_compatible: + raise exceptions.ConfigDoesNotAllowException(f"Tool '{job.tool_id}' cannot be rerun.") + return tool.to_json(trans, {}, job=job) - @require_admin - @expose_api - def update_job_lock(self, trans: ProvidesUserContext, payload, **kwd): - """ - * PUT /api/job_lock - return boolean indicating if job lock active. - """ - active = payload.get("active") - job_lock = JobLock(active=active) - return self.job_manager.update_job_lock(job_lock) + def __get_job(self, trans, job_id=None, dataset_id=None, **kwd): + if job_id is not None: + decoded_job_id = self.decode_id(job_id) + return self.job_manager.get_accessible_job(trans, decoded_job_id) + else: + hda_ldda = kwd.get("hda_ldda", "hda") + # Following checks dataset accessible + dataset_instance = self.get_hda_or_ldda(trans, hda_ldda=hda_ldda, dataset_id=dataset_id) + return dataset_instance.creating_job diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index 5048abcc36c8..ed2b363e868f 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -922,16 +922,6 @@ def connect_invocation_endpoint(endpoint_name, endpoint_suffix, action, conditio webapp, name_prefix="library_dataset_", path_prefix="/api/libraries/{library_id}/contents/{library_content_id}" ) - webapp.mapper.resource("job", "jobs", path_prefix="/api") - webapp.mapper.connect( - "job_search", "/api/jobs/search", controller="jobs", action="search", conditions=dict(method=["POST"]) - ) - webapp.mapper.connect( - "job_inputs", "/api/jobs/{id}/inputs", controller="jobs", action="inputs", conditions=dict(method=["GET"]) - ) - webapp.mapper.connect( - "job_outputs", "/api/jobs/{id}/outputs", controller="jobs", action="outputs", conditions=dict(method=["GET"]) - ) webapp.mapper.connect( "build_for_rerun", "/api/jobs/{id}/build_for_rerun", @@ -939,55 +929,6 @@ def connect_invocation_endpoint(endpoint_name, endpoint_suffix, action, conditio action="build_for_rerun", conditions=dict(method=["GET"]), ) - webapp.mapper.connect( - "resume", "/api/jobs/{id}/resume", controller="jobs", action="resume", conditions=dict(method=["PUT"]) - ) - webapp.mapper.connect( - "job_error", "/api/jobs/{id}/error", controller="jobs", action="error", conditions=dict(method=["POST"]) - ) - webapp.mapper.connect( - "common_problems", - "/api/jobs/{id}/common_problems", - controller="jobs", - action="common_problems", - conditions=dict(method=["GET"]), - ) - # Job metrics and parameters by job id or dataset id (for slightly different accessibility checking) - webapp.mapper.connect( - "destination_params", - "/api/jobs/{job_id}/destination_params", - controller="jobs", - action="destination_params", - conditions=dict(method=["GET"]), - ) - webapp.mapper.connect( - "metrics", - "/api/jobs/{job_id}/metrics", - controller="jobs", - action="metrics", - conditions=dict(method=["GET"]), - ) - webapp.mapper.connect( - "dataset_metrics", - "/api/datasets/{dataset_id}/metrics", - controller="jobs", - action="metrics", - conditions=dict(method=["GET"]), - ) - webapp.mapper.connect( - "parameters_display", - "/api/jobs/{job_id}/parameters_display", - controller="jobs", - action="parameters_display", - conditions=dict(method=["GET"]), - ) - webapp.mapper.connect( - "dataset_parameters_display", - "/api/datasets/{dataset_id}/parameters_display", - controller="jobs", - action="parameters_display", - conditions=dict(method=["GET"]), - ) # Job files controllers. Only for consumption by remote job runners. webapp.mapper.resource( diff --git a/lib/galaxy/webapps/galaxy/services/jobs.py b/lib/galaxy/webapps/galaxy/services/jobs.py index 5a92d629603a..95ceb3ede2b3 100644 --- a/lib/galaxy/webapps/galaxy/services/jobs.py +++ b/lib/galaxy/webapps/galaxy/services/jobs.py @@ -2,6 +2,7 @@ from typing import ( Any, Dict, + List, Optional, ) @@ -17,7 +18,13 @@ view_show_job, ) from galaxy.schema.fields import DecodedDatabaseIdField -from galaxy.schema.schema import JobIndexQueryPayload +from galaxy.schema.jobs import JobAssociation +from galaxy.schema.schema import ( + EncodedDatasetSourceId, + JobIndexQueryPayload, +) +from galaxy.security.idencoding import IdEncodingHelper +from galaxy.webapps.galaxy.services.base import ServiceBase class JobIndexViewEnum(str, Enum): @@ -29,17 +36,19 @@ class JobIndexPayload(JobIndexQueryPayload): view: JobIndexViewEnum = JobIndexViewEnum.collection -class JobsService: +class JobsService(ServiceBase): job_manager: JobManager job_search: JobSearch hda_manager: hdas.HDAManager def __init__( self, + security: IdEncodingHelper, job_manager: JobManager, job_search: JobSearch, hda_manager: hdas.HDAManager, ): + super().__init__(security=security) self.job_manager = job_manager self.job_search = job_search self.hda_manager = hda_manager @@ -92,3 +101,39 @@ def _check_nonadmin_access( raise exceptions.AdminRequiredException("Only admins can index the jobs with user details enabled") if decoded_user_id is not None and decoded_user_id != trans_user_id: raise exceptions.AdminRequiredException("Only admins can index the jobs of others") + + def get_job( + self, + trans: ProvidesUserContext, + job_id: Optional[int] = None, + dataset_id: Optional[int] = None, + hda_ldda: str = "hda", + ): + if job_id is not None: + return self.job_manager.get_accessible_job(trans, decoded_job_id=job_id) + elif dataset_id is not None: + # Following checks dataset accessible + if hda_ldda == "hda": + dataset_instance = self.hda_manager.get_accessible(id=dataset_id, user=trans.user) + else: + dataset_instance = self.hda_manager.ldda_manager.get(trans, id=dataset_id) + return dataset_instance.creating_job + else: + # Raise an exception if neither job_id nor dataset_id is provided + raise ValueError("Either job_id or dataset_id must be provided.") + + def dictify_associations(self, trans, *association_lists) -> List[JobAssociation]: + rval: List[JobAssociation] = [] + for association_list in association_lists: + rval.extend(self.__dictify_association(trans, a) for a in association_list) + return rval + + def __dictify_association(self, trans, job_dataset_association) -> JobAssociation: + dataset_dict = None + dataset = job_dataset_association.dataset + if dataset: + if isinstance(dataset, model.HistoryDatasetAssociation): + dataset_dict = EncodedDatasetSourceId(src="hda", id=dataset.id) + else: + dataset_dict = EncodedDatasetSourceId(src="ldda", id=dataset.id) + return JobAssociation(name=job_dataset_association.name, dataset=dataset_dict) diff --git a/lib/galaxy_test/api/test_jobs.py b/lib/galaxy_test/api/test_jobs.py index c2e289bd435f..af77499417d7 100644 --- a/lib/galaxy_test/api/test_jobs.py +++ b/lib/galaxy_test/api/test_jobs.py @@ -488,7 +488,7 @@ def _run_error_report(self, history_id): job_id = run_response["jobs"][0]["id"] self.dataset_populator.wait_for_job(job_id) dataset_id = run_response["outputs"][0]["id"] - response = self._post(f"jobs/{job_id}/error", data={"dataset_id": dataset_id}) + response = self._post(f"jobs/{job_id}/error", data={"dataset_id": dataset_id}, json=True) assert response.status_code == 200, response.text @skip_without_tool("detect_errors_aggressive") @@ -937,9 +937,95 @@ def test_job_build_for_rerun_list_list(self, history_id): ) assert rerun_content == run_content + @pytest.mark.require_new_history + def test_get_inputs_and_outputs(self, history_id): + dataset_id = self.__history_with_ok_dataset(history_id) + inputs = json.dumps({"input1": {"src": "hda", "id": dataset_id}}) + search_response = self._create_and_search_job(history_id, inputs, tool_id="cat1") + job_id = search_response.json()[0]["id"] + job_first_output_name, job_first_output_values = list(search_response.json()[0]["outputs"].items())[0] + # get the inputs of the job + job_response = self._get(f"jobs/{job_id}/inputs") + self._assert_status_code_is(job_response, 200) + job_first_input = job_response.json()[0] + # validate input response + assert job_first_input.get("name") == "input1" + assert job_first_input.get("dataset") == {"src": "hda", "id": dataset_id} + # get the outputs of the job + job_response = self._get(f"jobs/{job_id}/outputs") + self._assert_status_code_is(job_response, 200) + job_first_output = job_response.json()[0] + # validate output response + assert job_first_output.get("name") == job_first_output_name + assert job_first_output.get("dataset").get("id") == job_first_output_values.get("id") + assert job_first_output.get("dataset").get("src") == job_first_output_values.get("src") + + @pytest.mark.require_new_history + def test_delete_job(self, history_id): + dataset_id = self.__history_with_ok_dataset(history_id) + inputs = json.dumps({"input1": {"src": "hda", "id": dataset_id}}) + search_payload = self._search_payload(history_id=history_id, tool_id="cat1", inputs=inputs) + # create a job + tool_response = self._post("tools", data=search_payload) + job_id = tool_response.json()["jobs"][0]["id"] + # delete the job without message + delete_job_response = self._delete(f"jobs/{job_id}") + self._assert_status_code_is(delete_job_response, 200) + assert delete_job_response.json() is True + # now that we deleted the job we should not find it anymore + search_payload = self._search_payload(history_id=history_id, tool_id="cat1", inputs=inputs) + empty_search_response = self._post("jobs/search", data=search_payload, json=True) + self._assert_status_code_is(empty_search_response, 200) + assert len(empty_search_response.json()) == 0 + + @pytest.mark.require_new_history + def test_destination_params(self, history_id): + dataset_id = self.__history_with_ok_dataset(history_id) + inputs = json.dumps({"input1": {"src": "hda", "id": dataset_id}}) + search_response = self._create_and_search_job(history_id, inputs, tool_id="cat1") + job_id = search_response.json()[0]["id"] + destination_params_response = self._get(f"/api/jobs/{job_id}/destination_params", admin=True) + self._assert_status_code_is(destination_params_response, 200) + + @pytest.mark.require_new_history + def test_job_metrics(self, history_id): + dataset_id = self.__history_with_ok_dataset(history_id) + inputs = json.dumps({"input1": {"src": "hda", "id": dataset_id}}) + search_response = self._create_and_search_job(history_id, inputs, tool_id="cat1") + job_id = search_response.json()[0]["id"] + metrics_by_job_response = self._get(f"/api/jobs/{job_id}/metrics", data={"hda_ldda": "hda"}) + self._assert_status_code_is(metrics_by_job_response, 200) + metrics_by_dataset_response = self._get(f"/api/datasets/{dataset_id}/metrics", data={"hda_ldda": "hda"}) + self._assert_status_code_is(metrics_by_dataset_response, 200) + + @pytest.mark.require_new_history + def test_parameters_display(self, history_id): + dataset_id = self.__history_with_ok_dataset(history_id) + inputs = json.dumps({"input1": {"src": "hda", "id": dataset_id}}) + search_response = self._create_and_search_job(history_id, inputs, tool_id="cat1") + job_id = search_response.json()[0]["id"] + display_parameters_by_job_response = self._get( + f"/api/jobs/{job_id}/parameters_display", data={"hda_ldda": "hda"} + ) + self._assert_status_code_is(display_parameters_by_job_response, 200) + display_parameters_by_dataset_response = self._get( + f"/api/datasets/{dataset_id}/parameters_display", data={"hda_ldda": "hda"} + ) + self._assert_status_code_is(display_parameters_by_dataset_response, 200) + + def _create_and_search_job(self, history_id, inputs, tool_id): + # create a job + search_payload = self._search_payload(history_id=history_id, tool_id=tool_id, inputs=inputs) + tool_response = self._post("tools", data=search_payload) + self.dataset_populator.wait_for_tool_run(history_id, run_response=tool_response) + # search for the job and get the corresponding values + search_response = self._post("jobs/search", data=search_payload, json=True) + self._assert_status_code_is(search_response, 200) + return search_response + def _job_search(self, tool_id, history_id, inputs): search_payload = self._search_payload(history_id=history_id, tool_id=tool_id, inputs=inputs) - empty_search_response = self._post("jobs/search", data=search_payload) + empty_search_response = self._post("jobs/search", data=search_payload, json=True) self._assert_status_code_is(empty_search_response, 200) assert len(empty_search_response.json()) == 0 tool_response = self._post("tools", data=search_payload) @@ -966,7 +1052,7 @@ def _search(self, payload, expected_search_count=1): return search_count def _search_count(self, search_payload): - search_response = self._post("jobs/search", data=search_payload) + search_response = self._post("jobs/search", data=search_payload, json=True) self._assert_status_code_is(search_response, 200) search_json = search_response.json() return len(search_json)