1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
5 class Arvados::V1::SchemaController < ApplicationController
6 skip_before_action :catch_redirect_hint
7 skip_before_action :find_objects_for_index
8 skip_before_action :find_object_by_uuid
9 skip_before_action :load_filters_param
10 skip_before_action :load_limit_offset_order_params
11 skip_before_action :load_select_param
12 skip_before_action :load_read_auths
13 skip_before_action :load_where_param
14 skip_before_action :render_404_if_no_object
15 skip_before_action :require_auth_scope
20 expires_in 24.hours, public: true
21 send_json discovery_doc
27 'destroy' => 'delete',
32 HttpMethodDescriptionMap = {
40 # The discovery document has code to humanize most model names.
41 # These are exceptions that require some capitalization.
42 "ApiClientAuthorization" => "API client authorization",
43 "KeepService" => "Keep service",
46 SchemaDescriptionMap = {
47 # This hash contains descriptions for everything in the schema.
48 # Schemas are looked up by their model name.
49 # Schema properties are looked up by "{model_name}.{property_name}"
50 # and fall back to just the property name if that doesn't exist.
51 "ApiClientAuthorization" => "Arvados API client authorization token
53 This resource represents an API token a user may use to authenticate an
54 Arvados API request.",
55 "AuthorizedKey" => "Arvados authorized public key
57 This resource represents a public key a user may use to authenticate themselves
58 to services on the cluster. Its primary use today is to store SSH keys for
59 virtual machines (\"shell nodes\"). It may be extended to store other keys in
61 "Collection" => "Arvados data collection
63 A collection describes how a set of files is stored in data blocks in Keep,
64 along with associated metadata.",
65 "ComputedPermission" => "Arvados computed permission
67 Computed permissions do not correspond directly to any Arvados resource, but
68 provide a simple way to query the entire graph of permissions granted to
70 "ContainerRequest" => "Arvados container request
72 A container request represents a user's request that Arvados do some compute
73 work, along with full details about what work should be done. Arvados will
74 attempt to fulfill the request by mapping it to a matching container record,
75 running the work on demand if necessary.",
76 "Container" => "Arvados container record
78 A container represents compute work that has been or should be dispatched,
79 along with its results. A container can satisfy one or more container requests.",
80 "Group" => "Arvados group
82 Groups provide a way to organize users or data together, depending on their
84 "KeepService" => "Arvados Keep service
86 This resource stores information about a single Keep service in this Arvados
87 cluster that clients can contact to retrieve and store data.",
88 "Link" => "Arvados object link
90 A link provides a way to define relationships between Arvados objects,
91 depending on their `link_class`.",
92 "Log" => "Arvados log record
94 This resource represents a single log record about an event in this Arvados
95 cluster. Some individual Arvados services create log records. Users can also
97 "UserAgreement" => "Arvados user agreement
99 A user agreement is a collection with terms that users must agree to before
100 they can use this Arvados cluster.",
101 "User" => "Arvados user
103 A user represents a single individual or role who may be authorized to access
104 this Arvados cluster.",
105 "VirtualMachine" => "Arvados virtual machine (\"shell node\")
107 This resource stores information about a virtual machine or \"shell node\"
108 hosted on this Arvados cluster where users can log in and use preconfigured
109 Arvados client tools.",
110 "Workflow" => "Arvados workflow
112 A workflow contains workflow definition source code that Arvados can execute
113 along with associated metadata for users.",
115 # This section contains:
116 # * attributes shared across most resources
117 # * attributes shared across Collections and UserAgreements
118 # * attributes shared across Containers and ContainerRequests
120 "An array of strings that defines the command that the dispatcher should
121 execute inside this container.",
123 "The portable data hash of the Arvados collection that contains the image
124 to use for this container.",
125 "created_at" => "The time this %s was created.",
126 "current_version_uuid" => "The UUID of the current version of this %s.",
128 "A string that the defines the working directory that the dispatcher should
129 use when it executes the command inside this container.",
130 "delete_at" => "The time this %s will be permanently deleted.",
131 "description" => "A longer description of this %s assigned by a user.",
133 "A hash of string keys and values that defines the environment variables
134 for the dispatcher to set when it executes this container.",
136 "The number of files represented in this %s's `manifest_text`.
137 This attribute is read-only.",
139 "The total size in bytes of files represented in this %s's `manifest_text`.
140 This attribute is read-only.",
141 "is_trashed" => "A boolean flag to indicate whether or not this %s is trashed.",
143 "The manifest text that describes how files are constructed from data blocks
144 in this %s. Refer to the [manifest format][] reference for details.
146 [manifest format]: https://doc.arvados.org/architecture/manifest-format.html
149 "modified_at" => "The time this %s was last updated.",
150 "modified_by_user_uuid" => "The UUID of the user that last updated this %s.",
152 "A hash where each key names a directory inside this container, and its
153 value is an object that defines the mount source for that directory. Refer
154 to the [mount types reference][] for details.
156 [mount types reference]: https://doc.arvados.org/api/methods/containers.html#mount_types
159 "name" => "The name of this %s assigned by a user.",
161 "An array of strings of shell-style glob patterns that define which file(s)
162 and subdirectory(ies) under the `output_path` directory should be recorded in
163 the container's final output. Refer to the [glob patterns reference][] for details.
165 [glob patterns reference]: https://doc.arvados.org/api/methods/containers.html#glob_patterns
169 "A string that defines the file or directory path where the command
170 writes output that should be saved from this container.",
171 "output_properties" =>
172 "A hash of arbitrary metadata to set on the output collection of this %s.
173 Some keys may be reserved by Arvados or defined by a configured vocabulary.
174 Refer to the [metadata properties reference][] for details.
176 [metadata properties reference]: https://doc.arvados.org/api/properties.html
179 "output_storage_classes" =>
180 "An array of strings identifying the storage class(es) that should be set
181 on the output collection of this %s. Storage classes are configured by
182 the cluster administrator.",
183 "owner_uuid" => "The UUID of the user or group that owns this %s.",
184 "portable_data_hash" =>
185 "The portable data hash of this %s. This string provides a unique
186 and stable reference to these contents.",
187 "preserve_version" =>
188 "A boolean flag to indicate whether this specific version of this %s
189 should be persisted in cluster storage.",
191 "An integer between 0 and 1000 (inclusive) that represents this %s's
192 scheduling priority. 0 represents a request to be cancelled. Higher
193 values represent higher priority. Refer to the [priority reference][] for details.
195 [priority reference]: https://doc.arvados.org/api/methods/container_requests.html#priority
199 "A hash of arbitrary metadata for this %s.
200 Some keys may be reserved by Arvados or defined by a configured vocabulary.
201 Refer to the [metadata properties reference][] for details.
203 [metadata properties reference]: https://doc.arvados.org/api/properties.html
206 "replication_confirmed" =>
207 "The number of copies of data in this %s that the cluster has confirmed
209 "replication_confirmed_at" =>
210 "The last time the cluster confirmed that it met `replication_confirmed`
212 "replication_desired" =>
213 "The number of copies that should be made for data in this %s.",
214 "runtime_auth_scopes" =>
215 "The `scopes` from the API client authorization token used to run this %s.",
216 "runtime_constraints" =>
217 "A hash that identifies compute resources this container requires to run
218 successfully. See the [runtime constraints reference][] for details.
220 [runtime constraints reference]: https://doc.arvados.org/api/methods/containers.html#runtime_constraints
224 "The `api_token` from an Arvados API client authorization token that a
225 dispatcher should use to set up this container.",
226 "runtime_user_uuid" =>
227 "The UUID of the Arvados user associated with the API client authorization
228 token used to run this container.",
230 "A hash like `mounts`, but this attribute is only available through a
231 dedicated API before the container is run.",
232 "scheduling_parameters" =>
233 "A hash of scheduling parameters that should be passed to the underlying
234 dispatcher when this container is run.
235 See the [scheduling parameters reference][] for details.
237 [scheduling parameters reference]: https://doc.arvados.org/api/methods/containers.html#scheduling_parameters
240 "storage_classes_desired" =>
241 "An array of strings identifying the storage class(es) that should be used
242 for data in this %s. Storage classes are configured by the cluster administrator.",
243 "storage_classes_confirmed" =>
244 "An array of strings identifying the storage class(es) the cluster has
245 confirmed have a copy of this %s's data.",
246 "storage_classes_confirmed_at" =>
247 "The last time the cluster confirmed that data was stored on the storage
248 class(es) in `storage_classes_confirmed`.",
249 "trash_at" => "The time this %s will be trashed.",
251 "ApiClientAuthorization.api_token" =>
252 "The secret token that can be used to authorize Arvados API requests.",
253 "ApiClientAuthorization.created_by_ip_address" =>
254 "The IP address of the client that created this token.",
255 "ApiClientAuthorization.expires_at" =>
256 "The time after which this token is no longer valid for authorization.",
257 "ApiClientAuthorization.last_used_at" =>
258 "The last time this token was used to authorize a request.",
259 "ApiClientAuthorization.last_used_by_ip_address" =>
260 "The IP address of the client that last used this token.",
261 "ApiClientAuthorization.scopes" =>
262 "An array of strings identifying HTTP methods and API paths this token is
263 authorized to use. Refer to the [scopes reference][] for details.
265 [scopes reference]: https://doc.arvados.org/api/tokens.html#scopes
269 "An integer that counts which version of a %s this record
270 represents. Refer to [collection versioning][] for details. This attribute is
273 [collection versioning]: https://doc.arvados.org/user/topics/collection-versioning.html
277 "AuthorizedKey.authorized_user_uuid" =>
278 "The UUID of the Arvados user that is authorized by this key.",
279 "AuthorizedKey.expires_at" =>
280 "The time after which this key is no longer valid for authorization.",
281 "AuthorizedKey.key_type" =>
282 "A string identifying what type of service uses this key. Supported values are:
287 "AuthorizedKey.public_key" =>
288 "The full public key, in the format referenced by `key_type`.",
290 "ComputedPermission.user_uuid" =>
291 "The UUID of the Arvados user who has this permission.",
292 "ComputedPermission.target_uuid" =>
293 "The UUID of the Arvados object the user has access to.",
294 "ComputedPermission.perm_level" =>
295 "A string representing the user's level of access to the target object.
304 "Container.auth_uuid" =>
305 "The UUID of the Arvados API client authorization token that a dispatcher
306 should use to set up this container. This token is automatically created by
307 Arvados and this attribute automatically assigned unless a container is
308 created with `runtime_token`.",
310 "A float with the estimated cost of the cloud instance used to run this
311 container. The value is `0` if cost estimation is not available on this cluster.",
312 "Container.exit_code" =>
313 "An integer that records the Unix exit code of the `command` from a
314 finished container.",
315 "Container.gateway_address" =>
316 "A string with the address of the Arvados gateway server, in `HOST:PORT`
317 format. This is for internal use only.",
318 "Container.interactive_session_started" =>
319 "This flag is set true if any user starts an interactive shell inside the
321 "Container.lock_count" =>
322 "The number of times this container has been locked by a dispatcher. This
323 may be greater than 1 if a dispatcher locks a container but then execution is
324 interrupted for any reason.",
325 "Container.locked_by_uuid" =>
326 "The UUID of the Arvados API client authorization token that successfully
327 locked this container in preparation to execute it.",
329 "The portable data hash of the Arvados collection that contains this
331 "Container.output" =>
332 "The portable data hash of the Arvados collection that contains this
333 container's output file(s).",
334 "Container.progress" =>
335 "A float between 0.0 and 1.0 (inclusive) that represents the container's
336 execution progress. This attribute is not implemented yet.",
337 "Container.runtime_status" =>
338 "A hash with status updates from a running container.
339 Refer to the [runtime status reference][] for details.
341 [runtime status reference]: https://doc.arvados.org/api/methods/containers.html#runtime_status
344 "Container.subrequests_cost" =>
345 "A float with the estimated cost of all cloud instances used to run this
346 container and all its subrequests. The value is `0` if cost estimation is not
347 available on this cluster.",
349 "A string representing the container's current execution status. Possible
352 * `\"Queued\"` --- This container has not been dispatched yet.
353 * `\"Locked\"` --- A dispatcher has claimed this container in preparation to run it.
354 * `\"Running\"` --- A dispatcher is running this container.
355 * `\"Cancelled\"` --- Container execution has been cancelled by user request.
356 * `\"Complete\"` --- A dispatcher ran this container to completion and recorded the results.
360 "ContainerRequest.auth_uuid" =>
361 "The UUID of the Arvados API client authorization token that a
362 dispatcher should use to set up a corresponding container. This token is
363 automatically created by Arvados and this attribute automatically assigned
364 unless a container request is created with `runtime_token`.",
365 "ContainerRequest.container_count" =>
366 "An integer that records how many times Arvados has attempted to dispatch
367 a container to fulfill this container request.",
368 "ContainerRequest.container_count_max" =>
369 "An integer that defines the maximum number of times Arvados should attempt
370 to dispatch a container to fulfill this container request.",
371 "ContainerRequest.container_uuid" =>
372 "The UUID of the container that fulfills this container request, if any.",
373 "ContainerRequest.cumulative_cost" =>
374 "A float with the estimated cost of all cloud instances used to run
375 container(s) to fulfill this container request and their subrequests.
376 The value is `0` if cost estimation is not available on this cluster.",
377 "ContainerRequest.expires_at" =>
378 "The time after which this %s will no longer be fulfilled.",
379 "ContainerRequest.filters" =>
380 "An array of filters that limit which existing containers are eligible to
381 satisfy this container request. Refer to the [filters reference][] for details.
383 [filters reference]: https://doc.arvados.org/api/methods.html#filters
386 "ContainerRequest.log_uuid" =>
387 "The UUID of the Arvados collection that contains logs for all the
388 container(s) that were dispatched to fulfill this container request.",
389 "ContainerRequest.output_name" =>
390 "The name to set on the output collection of this container request.",
391 "ContainerRequest.output_ttl" =>
392 "An integer in seconds. If greater than zero, when an output collection is
393 created for this container request, its `expires_at` attribute will be set this
395 "ContainerRequest.output_uuid" =>
396 "The UUID of the Arvados collection that contains output for all the
397 container(s) that were dispatched to fulfill this container request.",
398 "ContainerRequest.requesting_container_uuid" =>
399 "The UUID of the container that created this container request, if any.",
400 "ContainerRequest.state" =>
401 "A string indicating where this container request is in its lifecycle.
404 * `\"Uncommitted\"` --- The container request has not been finalized and can still be edited.
405 * `\"Committed\"` --- The container request is ready to be fulfilled.
406 * `\"Final\"` --- The container request has been fulfilled or cancelled.
409 "ContainerRequest.use_existing" =>
410 "A boolean flag. If set, Arvados may choose to satisfy this container
411 request with an eligible container that already exists. Otherwise, Arvados will
412 satisfy this container request with a newer container, which will usually result
413 in the container running again.",
415 "Group.group_class" =>
416 "A string representing which type of group this is. One of:
418 * `\"filter\"` --- A virtual project whose contents are selected dynamically by filters.
419 * `\"project\"` --- An Arvados project that can contain collections,
420 container records, workflows, and subprojects.
421 * `\"role\"` --- A group of users that can be granted permissions in Arvados.
424 "Group.frozen_by_uuid" =>
425 "The UUID of the user that has frozen this group, if any. Frozen projects
426 cannot have their contents or metadata changed, even by admins.",
428 "KeepService.service_host" => "The DNS hostname of this %s.",
429 "KeepService.service_port" => "The TCP port where this %s listens.",
430 "KeepService.service_ssl_flag" =>
431 "A boolean flag that indicates whether or not this %s uses TLS/SSL.",
432 "KeepService.service_type" =>
433 "A string that describes which type of %s this is. One of:
435 * `\"disk\"` --- A service that stores blocks on a local filesystem.
436 * `\"blob\"` --- A service that stores blocks in a cloud object store.
437 * `\"proxy\"` --- A keepproxy service.
440 "KeepService.read_only" =>
441 "A boolean flag. If set, this %s does not accept requests to write data
442 blocks; it only serves blocks it already has.",
445 "The UUID of the Arvados object that is the originator or actor in this
446 relationship. May be null.",
448 "A string that defines which kind of link this is. One of:
450 * `\"permission\"` --- This link grants a permission to the user or group
451 referenced by `head_uuid` to the object referenced by `tail_uuid`. The
452 access level is set by `name`.
453 * `\"star\"` --- This link represents a \"favorite.\" The user referenced
454 by `head_uuid` wants quick access to the object referenced by `tail_uuid`.
455 * `\"tag\"` --- This link represents an unstructured metadata tag. The object
456 referenced by `tail_uuid` has the tag defined by `name`.
460 "The primary value of this link. For `\"permission\"` links, this is one of
461 `\"can_read\"`, `\"can_write\"`, or `\"can_manage\"`.",
463 "The UUID of the Arvados object that is the target of this relationship.",
466 "The serial number of this log. You can use this in filters to query logs
467 that were created before/after another.",
469 "An arbitrary short string that classifies what type of log this is.",
470 "Log.object_owner_uuid" =>
471 "The `owner_uuid` of the object referenced by `object_uuid` at the time
472 this log was created.",
474 "The UUID of the Arvados object that this log pertains to, such as a user
477 "A text string that describes the logged event. This is the primary
478 attribute for simple logs.",
480 "User.email" => "This user's email address.",
481 "User.first_name" => "This user's first name.",
482 "User.identity_url" =>
483 "A URL that represents this user with the cluster's identity provider.",
485 "A boolean flag. If unset, this user is not permitted to make any Arvados
488 "A boolean flag. If set, this user is an administrator of the Arvados
489 cluster, and automatically passes most permissions checks.",
490 "User.last_name" => "This user's last name.",
491 "User.prefs" => "A hash that stores cluster-wide user preferences.",
492 "User.username" => "This user's Unix username on virtual machines.",
494 "VirtualMachine.hostname" =>
495 "The DNS hostname where users should access this %s.",
497 "Workflow.definition" => "A string with the CWL source of this %s.",
501 Rails.application.eager_load!
503 Rails.configuration.RemoteClusters.each {|k,v| if k != :"*" then remoteHosts[k] = v["Host"] end }
505 kind: "discovery#restDescription",
506 discoveryVersion: "v1",
510 # format is YYYYMMDD, must be fixed width (needs to be lexically
511 # sortable), updated manually, may be used by clients to
512 # determine availability of API server features.
513 revision: "20240627",
514 source_version: AppVersion.hash,
515 sourceVersion: AppVersion.hash, # source_version should be deprecated in the future
516 packageVersion: AppVersion.package_version,
517 generatedAt: db_current_time.iso8601,
518 title: "Arvados API",
519 description: "The API to interact with Arvados.",
520 documentationLink: "http://doc.arvados.org/api/index.html",
521 defaultCollectionReplication: Rails.configuration.Collections.DefaultReplication,
523 baseUrl: root_url + "arvados/v1/",
524 basePath: "/arvados/v1/",
526 servicePath: "arvados/v1/",
528 uuidPrefix: Rails.configuration.ClusterID,
529 defaultTrashLifetime: Rails.configuration.Collections.DefaultTrashLifetime,
530 blobSignatureTtl: Rails.configuration.Collections.BlobSigningTTL,
531 maxRequestSize: Rails.configuration.API.MaxRequestSize,
532 maxItemsPerResponse: Rails.configuration.API.MaxItemsPerResponse,
533 dockerImageFormats: Rails.configuration.Containers.SupportedDockerImageFormats.keys,
534 crunchLogUpdatePeriod: Rails.configuration.Containers.Logging.LogUpdatePeriod,
535 crunchLogUpdateSize: Rails.configuration.Containers.Logging.LogUpdateSize,
536 remoteHosts: remoteHosts,
537 remoteHostsViaDNS: Rails.configuration.RemoteClusters["*"].Proxy,
538 websocketUrl: Rails.configuration.Services.Websocket.ExternalURL.to_s,
539 workbenchUrl: Rails.configuration.Services.Workbench1.ExternalURL.to_s,
540 workbench2Url: Rails.configuration.Services.Workbench2.ExternalURL.to_s,
541 keepWebServiceUrl: Rails.configuration.Services.WebDAV.ExternalURL.to_s,
545 description: "Data format for the response.",
551 "Responses with Content-Type of application/json"
557 description: "Selector specifying which fields to include in a partial response.",
562 description: "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
567 description: "OAuth 2.0 token for the current user.",
574 "https://api.arvados.org/auth/arvados" => {
575 description: "View and manage objects"
577 "https://api.arvados.org/auth/arvados.readonly" => {
578 description: "View objects"
587 ActiveRecord::Base.descendants.reject(&:abstract_class?).sort_by(&:to_s).each do |k|
589 ctl_class = "Arvados::V1::#{k.to_s.pluralize}Controller".constantize
591 # No controller -> no discovery.
594 human_name = ModelHumanNameMap[k.to_s] || k.to_s.underscore.humanize.downcase
595 object_properties = {}
597 select { |col| k.selectable_attributes.include? col.name }.
599 if k.serialized_attributes.has_key? col.name
600 col_type = k.serialized_attributes[col.name].object_class.to_s
601 elsif k.attribute_types[col.name].is_a? JsonbType::Hash
603 elsif k.attribute_types[col.name].is_a? JsonbType::Array
604 col_type = Array.to_s
609 SchemaDescriptionMap["#{k}.#{col.name}"] ||
610 SchemaDescriptionMap[col.name] ||
612 if k.attribute_types[col.name].type == :datetime
613 desc_fmt += " The string encodes a UTC date and time in ISO 8601 format."
615 object_properties[col.name] = {
616 description: desc_fmt % human_name,
620 discovery[:schemas][k.to_s + 'List'] = {
622 description: "A list of #{k} objects.",
627 description: "Object type. Always arvados##{k.to_s.camelcase(:lower)}List.",
628 default: "arvados##{k.to_s.camelcase(:lower)}List"
632 description: "List cache version."
636 description: "An array of matching #{k} objects.",
643 discovery[:schemas][k.to_s] = {
645 description: SchemaDescriptionMap[k.to_s] || "Arvados #{human_name}.",
651 description: "Object cache version."
653 }.merge(object_properties)
655 if k.respond_to? :uuid_prefix
656 discovery[:schemas][k.to_s][:uuidPrefix] ||= k.uuid_prefix
657 discovery[:schemas][k.to_s][:properties][:uuid] ||= {
659 description: "This #{human_name}'s Arvados UUID, like `zzzzz-#{k.uuid_prefix}-12345abcde67890`."
662 discovery[:resources][k.to_s.underscore.pluralize] = {
665 id: "arvados.#{k.to_s.underscore.pluralize}.get",
666 path: "#{k.to_s.underscore.pluralize}/{uuid}",
668 description: "Get a #{k.to_s} record by UUID.",
672 description: "The UUID of the #{k.to_s} to return.",
684 "https://api.arvados.org/auth/arvados",
685 "https://api.arvados.org/auth/arvados.readonly"
689 id: "arvados.#{k.to_s.underscore.pluralize}.list",
690 path: k.to_s.underscore.pluralize,
692 description: "Retrieve a #{k.to_s}List.",
696 "$ref" => "#{k.to_s}List"
699 "https://api.arvados.org/auth/arvados",
700 "https://api.arvados.org/auth/arvados.readonly"
704 id: "arvados.#{k.to_s.underscore.pluralize}.create",
705 path: "#{k.to_s.underscore.pluralize}",
707 description: "Create a new #{k.to_s}.",
712 k.to_s.underscore => {
721 "https://api.arvados.org/auth/arvados"
725 id: "arvados.#{k.to_s.underscore.pluralize}.update",
726 path: "#{k.to_s.underscore.pluralize}/{uuid}",
728 description: "Update attributes of an existing #{k.to_s}.",
732 description: "The UUID of the #{k.to_s} to update.",
740 k.to_s.underscore => {
749 "https://api.arvados.org/auth/arvados"
753 id: "arvados.#{k.to_s.underscore.pluralize}.delete",
754 path: "#{k.to_s.underscore.pluralize}/{uuid}",
755 httpMethod: "DELETE",
756 description: "Delete an existing #{k.to_s}.",
760 description: "The UUID of the #{k.to_s} to delete.",
769 "https://api.arvados.org/auth/arvados"
774 # Check for Rails routes that don't match the usual actions
776 d_methods = discovery[:resources][k.to_s.underscore.pluralize][:methods]
777 Rails.application.routes.routes.each do |route|
778 action = route.defaults[:action]
779 httpMethod = ['GET', 'POST', 'PUT', 'DELETE'].map { |method|
780 method if route.verb.match(method)
783 route.defaults[:controller] == 'arvados/v1/' + k.to_s.underscore.pluralize &&
784 ctl_class.action_methods.include?(action)
785 method_name = ActionNameMap[action] || action
786 method_key = method_name.to_sym
787 if !d_methods[method_key]
789 id: "arvados.#{k.to_s.underscore.pluralize}.#{method_name}",
790 path: route.path.spec.to_s.sub('/arvados/v1/','').sub('(.:format)','').sub(/:(uu)?id/,'{uuid}'),
791 httpMethod: httpMethod,
792 description: ctl_class.send("_#{method_name}_method_description".to_sym),
795 "$ref" => (method_name == 'list' ? "#{k.to_s}List" : k.to_s)
798 "https://api.arvados.org/auth/arvados"
801 route.segment_keys.each do |key|
807 description = "The UUID of the #{k} to #{HttpMethodDescriptionMap[httpMethod]}."
811 method[:parameters][key] = {
813 description: description,
819 # We already built a generic method description, but we
820 # might find some more required parameters through
822 method = d_methods[method_key]
824 if ctl_class.respond_to? "_#{action}_requires_parameters".to_sym
825 ctl_class.send("_#{action}_requires_parameters".to_sym).each do |l, v|
827 method[:parameters][l] = v
829 method[:parameters][l] = {}
831 if !method[:parameters][l][:default].nil?
832 # The JAVA SDK is sensitive to all values being strings
833 method[:parameters][l][:default] = method[:parameters][l][:default].to_s
835 method[:parameters][l][:type] ||= 'string'
836 method[:parameters][l][:description] ||= ''
837 method[:parameters][l][:location] = (route.segment_keys.include?(l) ? 'path' : 'query')
838 if method[:parameters][l][:required].nil?
839 method[:parameters][l][:required] = v != false
843 d_methods[method_key] = method
848 # The computed_permissions controller does not offer all of the
849 # usual methods and attributes. Modify discovery doc accordingly.
850 discovery[:resources]['computed_permissions'][:methods].select! do |method|
853 discovery[:resources]['computed_permissions'][:methods][:list][:parameters].reject! do |param|
854 [:cluster_id, :bypass_federation, :offset].include?(param)
856 discovery[:schemas]['ComputedPermission'].delete(:uuidPrefix)
857 discovery[:schemas]['ComputedPermission'][:properties].reject! do |prop|
858 [:uuid, :etag].include?(prop)
860 discovery[:schemas]['ComputedPermission'][:properties]['perm_level'][:type] = 'string'
862 # The 'replace_files' option is implemented in lib/controller,
863 # not Rails -- we just need to add it here so discovery-aware
864 # clients know how to validate it.
865 [:create, :update].each do |action|
866 discovery[:resources]['collections'][:methods][action][:parameters]['replace_files'] = {
869 "Add, delete, and replace files and directories with new content
870 and/or content from other collections. Refer to the
871 [replace_files reference][] for details.
873 [replace_files reference]: https://doc.arvados.org/api/methods/collections.html#replace_files
879 additionalProperties: {type: 'string'},
883 discovery[:resources]['configs'] = {
886 id: "arvados.configs.get",
889 description: "Get this cluster's public configuration settings.",
897 "https://api.arvados.org/auth/arvados",
898 "https://api.arvados.org/auth/arvados.readonly"
904 discovery[:resources]['vocabularies'] = {
907 id: "arvados.vocabularies.get",
910 description: "Get this cluster's configured vocabulary definition.
912 Refer to [metadata vocabulary documentation][] for details.
914 [metadata vocabulary documentation]: https://doc.aravdos.org/admin/metadata-vocabulary.html
924 "https://api.arvados.org/auth/arvados",
925 "https://api.arvados.org/auth/arvados.readonly"
931 discovery[:resources]['sys'] = {
934 id: "arvados.sys.trash_sweep",
935 path: "sys/trash_sweep",
938 "Run scheduled data trash and sweep operations across this cluster's Keep services.",
946 "https://api.arvados.org/auth/arvados",
947 "https://api.arvados.org/auth/arvados.readonly"
953 Rails.configuration.API.DisabledAPIs.each do |method, _|
954 ctrl, action = method.to_s.split('.', 2)
955 next if ctrl.in?(['api_clients', 'job_tasks', 'jobs', 'keep_disks', 'nodes', 'pipeline_instances', 'pipeline_templates', 'repositories'])
956 discovery[:resources][ctrl][:methods].delete(action.to_sym)