anyscale 0.26.19__py3-none-any.whl → 0.26.20__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. anyscale/_private/docgen/models.md +1 -1
  2. anyscale/client/README.md +6 -1
  3. anyscale/client/openapi_client/__init__.py +3 -0
  4. anyscale/client/openapi_client/api/default_api.py +269 -17
  5. anyscale/client/openapi_client/models/__init__.py +3 -0
  6. anyscale/client/openapi_client/models/decorated_production_job_state_transition.py +2 -2
  7. anyscale/client/openapi_client/models/job_queue_sort_directive.py +148 -0
  8. anyscale/client/openapi_client/models/job_queue_sort_field.py +107 -0
  9. anyscale/client/openapi_client/models/job_queues_query.py +31 -3
  10. anyscale/client/openapi_client/models/production_job_state_transition.py +2 -2
  11. anyscale/client/openapi_client/models/update_job_queue_request.py +150 -0
  12. anyscale/commands/command_examples.py +58 -0
  13. anyscale/commands/job_commands.py +2 -2
  14. anyscale/commands/job_queue_commands.py +172 -0
  15. anyscale/controllers/job_controller.py +215 -3
  16. anyscale/scripts.py +3 -0
  17. anyscale/sdk/anyscale_client/models/production_job_state_transition.py +2 -2
  18. anyscale/util.py +3 -1
  19. anyscale/utils/connect_helpers.py +34 -0
  20. anyscale/version.py +1 -1
  21. anyscale/workspace/_private/workspace_sdk.py +19 -6
  22. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/METADATA +1 -1
  23. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/RECORD +28 -24
  24. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/LICENSE +0 -0
  25. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/NOTICE +0 -0
  26. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/WHEEL +0 -0
  27. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/entry_points.txt +0 -0
  28. {anyscale-0.26.19.dist-info → anyscale-0.26.20.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,107 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Managed Ray API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by: https://openapi-generator.tech
10
+ """
11
+
12
+
13
+ import pprint
14
+ import re # noqa: F401
15
+
16
+ import six
17
+
18
+ from openapi_client.configuration import Configuration
19
+
20
+
21
+ class JobQueueSortField(object):
22
+ """NOTE: This class is auto generated by OpenAPI Generator.
23
+ Ref: https://openapi-generator.tech
24
+
25
+ Do not edit the class manually.
26
+ """
27
+
28
+ """
29
+ allowed enum values
30
+ """
31
+ ID = "ID"
32
+ NAME = "NAME"
33
+ CREATED_AT = "CREATED_AT"
34
+ CREATOR_ID = "CREATOR_ID"
35
+ CREATOR_EMAIL = "CREATOR_EMAIL"
36
+ PROJECT_ID = "PROJECT_ID"
37
+ CLOUD_ID = "CLOUD_ID"
38
+ QUEUE_STATE = "QUEUE_STATE"
39
+ CLUSTER_STATE = "CLUSTER_STATE"
40
+
41
+ allowable_values = [ID, NAME, CREATED_AT, CREATOR_ID, CREATOR_EMAIL, PROJECT_ID, CLOUD_ID, QUEUE_STATE, CLUSTER_STATE] # noqa: E501
42
+
43
+ """
44
+ Attributes:
45
+ openapi_types (dict): The key is attribute name
46
+ and the value is attribute type.
47
+ attribute_map (dict): The key is attribute name
48
+ and the value is json key in definition.
49
+ """
50
+ openapi_types = {
51
+ }
52
+
53
+ attribute_map = {
54
+ }
55
+
56
+ def __init__(self, local_vars_configuration=None): # noqa: E501
57
+ """JobQueueSortField - a model defined in OpenAPI""" # noqa: E501
58
+ if local_vars_configuration is None:
59
+ local_vars_configuration = Configuration()
60
+ self.local_vars_configuration = local_vars_configuration
61
+ self.discriminator = None
62
+
63
+ def to_dict(self):
64
+ """Returns the model properties as a dict"""
65
+ result = {}
66
+
67
+ for attr, _ in six.iteritems(self.openapi_types):
68
+ value = getattr(self, attr)
69
+ if isinstance(value, list):
70
+ result[attr] = list(map(
71
+ lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
72
+ value
73
+ ))
74
+ elif hasattr(value, "to_dict"):
75
+ result[attr] = value.to_dict()
76
+ elif isinstance(value, dict):
77
+ result[attr] = dict(map(
78
+ lambda item: (item[0], item[1].to_dict())
79
+ if hasattr(item[1], "to_dict") else item,
80
+ value.items()
81
+ ))
82
+ else:
83
+ result[attr] = value
84
+
85
+ return result
86
+
87
+ def to_str(self):
88
+ """Returns the string representation of the model"""
89
+ return pprint.pformat(self.to_dict())
90
+
91
+ def __repr__(self):
92
+ """For `print` and `pprint`"""
93
+ return self.to_str()
94
+
95
+ def __eq__(self, other):
96
+ """Returns true if both objects are equal"""
97
+ if not isinstance(other, JobQueueSortField):
98
+ return False
99
+
100
+ return self.to_dict() == other.to_dict()
101
+
102
+ def __ne__(self, other):
103
+ """Returns true if both objects are not equal"""
104
+ if not isinstance(other, JobQueueSortField):
105
+ return True
106
+
107
+ return self.to_dict() != other.to_dict()
@@ -38,7 +38,8 @@ class JobQueuesQuery(object):
38
38
  'cluster_status': 'SessionState',
39
39
  'project_id': 'str',
40
40
  'cloud_id': 'str',
41
- 'paging': 'PageQuery'
41
+ 'paging': 'PageQuery',
42
+ 'sorting_directives': 'list[JobQueueSortDirective]'
42
43
  }
43
44
 
44
45
  attribute_map = {
@@ -47,10 +48,11 @@ class JobQueuesQuery(object):
47
48
  'cluster_status': 'cluster_status',
48
49
  'project_id': 'project_id',
49
50
  'cloud_id': 'cloud_id',
50
- 'paging': 'paging'
51
+ 'paging': 'paging',
52
+ 'sorting_directives': 'sorting_directives'
51
53
  }
52
54
 
53
- def __init__(self, name=None, creator_id=None, cluster_status=None, project_id=None, cloud_id=None, paging=None, local_vars_configuration=None): # noqa: E501
55
+ def __init__(self, name=None, creator_id=None, cluster_status=None, project_id=None, cloud_id=None, paging=None, sorting_directives=None, local_vars_configuration=None): # noqa: E501
54
56
  """JobQueuesQuery - a model defined in OpenAPI""" # noqa: E501
55
57
  if local_vars_configuration is None:
56
58
  local_vars_configuration = Configuration()
@@ -62,6 +64,7 @@ class JobQueuesQuery(object):
62
64
  self._project_id = None
63
65
  self._cloud_id = None
64
66
  self._paging = None
67
+ self._sorting_directives = None
65
68
  self.discriminator = None
66
69
 
67
70
  if name is not None:
@@ -76,6 +79,8 @@ class JobQueuesQuery(object):
76
79
  self.cloud_id = cloud_id
77
80
  if paging is not None:
78
81
  self.paging = paging
82
+ if sorting_directives is not None:
83
+ self.sorting_directives = sorting_directives
79
84
 
80
85
  @property
81
86
  def name(self):
@@ -215,6 +220,29 @@ class JobQueuesQuery(object):
215
220
 
216
221
  self._paging = paging
217
222
 
223
+ @property
224
+ def sorting_directives(self):
225
+ """Gets the sorting_directives of this JobQueuesQuery. # noqa: E501
226
+
227
+ List of sorting criteria (multi-field sort supported). # noqa: E501
228
+
229
+ :return: The sorting_directives of this JobQueuesQuery. # noqa: E501
230
+ :rtype: list[JobQueueSortDirective]
231
+ """
232
+ return self._sorting_directives
233
+
234
+ @sorting_directives.setter
235
+ def sorting_directives(self, sorting_directives):
236
+ """Sets the sorting_directives of this JobQueuesQuery.
237
+
238
+ List of sorting criteria (multi-field sort supported). # noqa: E501
239
+
240
+ :param sorting_directives: The sorting_directives of this JobQueuesQuery. # noqa: E501
241
+ :type: list[JobQueueSortDirective]
242
+ """
243
+
244
+ self._sorting_directives = sorting_directives
245
+
218
246
  def to_dict(self):
219
247
  """Returns the model properties as a dict"""
220
248
  result = {}
@@ -108,7 +108,7 @@ class ProductionJobStateTransition(object):
108
108
  def state_transitioned_at(self):
109
109
  """Gets the state_transitioned_at of this ProductionJobStateTransition. # noqa: E501
110
110
 
111
- The last time the state of this job was updated. This includes updates to the state and to the goal state # noqa: E501
111
+ The last time the state of this job was updated # noqa: E501
112
112
 
113
113
  :return: The state_transitioned_at of this ProductionJobStateTransition. # noqa: E501
114
114
  :rtype: datetime
@@ -119,7 +119,7 @@ class ProductionJobStateTransition(object):
119
119
  def state_transitioned_at(self, state_transitioned_at):
120
120
  """Sets the state_transitioned_at of this ProductionJobStateTransition.
121
121
 
122
- The last time the state of this job was updated. This includes updates to the state and to the goal state # noqa: E501
122
+ The last time the state of this job was updated # noqa: E501
123
123
 
124
124
  :param state_transitioned_at: The state_transitioned_at of this ProductionJobStateTransition. # noqa: E501
125
125
  :type: datetime
@@ -0,0 +1,150 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Managed Ray API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by: https://openapi-generator.tech
10
+ """
11
+
12
+
13
+ import pprint
14
+ import re # noqa: F401
15
+
16
+ import six
17
+
18
+ from openapi_client.configuration import Configuration
19
+
20
+
21
+ class UpdateJobQueueRequest(object):
22
+ """NOTE: This class is auto generated by OpenAPI Generator.
23
+ Ref: https://openapi-generator.tech
24
+
25
+ Do not edit the class manually.
26
+ """
27
+
28
+ """
29
+ Attributes:
30
+ openapi_types (dict): The key is attribute name
31
+ and the value is attribute type.
32
+ attribute_map (dict): The key is attribute name
33
+ and the value is json key in definition.
34
+ """
35
+ openapi_types = {
36
+ 'idle_timeout_sec': 'int',
37
+ 'max_concurrency': 'int'
38
+ }
39
+
40
+ attribute_map = {
41
+ 'idle_timeout_sec': 'idle_timeout_sec',
42
+ 'max_concurrency': 'max_concurrency'
43
+ }
44
+
45
+ def __init__(self, idle_timeout_sec=None, max_concurrency=None, local_vars_configuration=None): # noqa: E501
46
+ """UpdateJobQueueRequest - a model defined in OpenAPI""" # noqa: E501
47
+ if local_vars_configuration is None:
48
+ local_vars_configuration = Configuration()
49
+ self.local_vars_configuration = local_vars_configuration
50
+
51
+ self._idle_timeout_sec = None
52
+ self._max_concurrency = None
53
+ self.discriminator = None
54
+
55
+ if idle_timeout_sec is not None:
56
+ self.idle_timeout_sec = idle_timeout_sec
57
+ if max_concurrency is not None:
58
+ self.max_concurrency = max_concurrency
59
+
60
+ @property
61
+ def idle_timeout_sec(self):
62
+ """Gets the idle_timeout_sec of this UpdateJobQueueRequest. # noqa: E501
63
+
64
+ Max number of jobs to be run concurrently. # noqa: E501
65
+
66
+ :return: The idle_timeout_sec of this UpdateJobQueueRequest. # noqa: E501
67
+ :rtype: int
68
+ """
69
+ return self._idle_timeout_sec
70
+
71
+ @idle_timeout_sec.setter
72
+ def idle_timeout_sec(self, idle_timeout_sec):
73
+ """Sets the idle_timeout_sec of this UpdateJobQueueRequest.
74
+
75
+ Max number of jobs to be run concurrently. # noqa: E501
76
+
77
+ :param idle_timeout_sec: The idle_timeout_sec of this UpdateJobQueueRequest. # noqa: E501
78
+ :type: int
79
+ """
80
+
81
+ self._idle_timeout_sec = idle_timeout_sec
82
+
83
+ @property
84
+ def max_concurrency(self):
85
+ """Gets the max_concurrency of this UpdateJobQueueRequest. # noqa: E501
86
+
87
+ Max period of time queue will be accepting new jobs, before being sealed off and its associated cluster being shutdown # noqa: E501
88
+
89
+ :return: The max_concurrency of this UpdateJobQueueRequest. # noqa: E501
90
+ :rtype: int
91
+ """
92
+ return self._max_concurrency
93
+
94
+ @max_concurrency.setter
95
+ def max_concurrency(self, max_concurrency):
96
+ """Sets the max_concurrency of this UpdateJobQueueRequest.
97
+
98
+ Max period of time queue will be accepting new jobs, before being sealed off and its associated cluster being shutdown # noqa: E501
99
+
100
+ :param max_concurrency: The max_concurrency of this UpdateJobQueueRequest. # noqa: E501
101
+ :type: int
102
+ """
103
+
104
+ self._max_concurrency = max_concurrency
105
+
106
+ def to_dict(self):
107
+ """Returns the model properties as a dict"""
108
+ result = {}
109
+
110
+ for attr, _ in six.iteritems(self.openapi_types):
111
+ value = getattr(self, attr)
112
+ if isinstance(value, list):
113
+ result[attr] = list(map(
114
+ lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
115
+ value
116
+ ))
117
+ elif hasattr(value, "to_dict"):
118
+ result[attr] = value.to_dict()
119
+ elif isinstance(value, dict):
120
+ result[attr] = dict(map(
121
+ lambda item: (item[0], item[1].to_dict())
122
+ if hasattr(item[1], "to_dict") else item,
123
+ value.items()
124
+ ))
125
+ else:
126
+ result[attr] = value
127
+
128
+ return result
129
+
130
+ def to_str(self):
131
+ """Returns the string representation of the model"""
132
+ return pprint.pformat(self.to_dict())
133
+
134
+ def __repr__(self):
135
+ """For `print` and `pprint`"""
136
+ return self.to_str()
137
+
138
+ def __eq__(self, other):
139
+ """Returns true if both objects are equal"""
140
+ if not isinstance(other, UpdateJobQueueRequest):
141
+ return False
142
+
143
+ return self.to_dict() == other.to_dict()
144
+
145
+ def __ne__(self, other):
146
+ """Returns true if both objects are not equal"""
147
+ if not isinstance(other, UpdateJobQueueRequest):
148
+ return True
149
+
150
+ return self.to_dict() != other.to_dict()
@@ -77,6 +77,64 @@ NAME ID COST PROJECT NAME CLUSTER NAME
77
77
  my-job prodjob_s9x4uzc5jnkt5z53g4tujb3y2e 0 default cluster_for_prodjob_s9x4uzc5jnkt5z53g4tujb3y2e SUCCESS doc@anyscale.com python main.py
78
78
  """
79
79
 
80
+ JOB_QUEUE_LIST = """\
81
+ $ anyscale job-queue list
82
+ Output
83
+ JOB QUEUES:
84
+ ID NAME CLUSTER ID CREATOR ID MAX CONCURRENCY IDLE TIMEOUT SEC CURRENT CLUSTER STATE
85
+ jq_h8fcze2qkr8wttuuvapi1hvyuc queue_3 ses_cjr7uaf1yh2ue5uzvd11p24p4u usr_we8x7d7u8hq8mj2488ed9x47n6 3 5000 Terminated
86
+ jq_v5bx9z1sd4pbxasxhdms37j4gi queue_2 ses_k86raeu6k1t6z1bvyejn3vblad usr_we8x7d7u8hq8mj2488ed9x47n6 10 5000 Terminated
87
+ jq_ni6hk66nt3194msr7hzzj9daun queue_1 ses_uhb8a9gamtarz68kcurpjh86sa usr_we8x7d7u8hq8mj2488ed9x47n6 10 5000 Terminated
88
+ """
89
+
90
+ JOB_QUEUE_INFO = """\
91
+ $ anyscale job-queue info --id jq_h8fcze2qkr8wttuuvapi1hvyuc
92
+ Output
93
+ ID : jq_h8fcze2qkr8wttuuvapi1hvyuc
94
+ USER PROVIDED ID : queue_3
95
+ NAME : queue_3
96
+ CURRENT JOB QUEUE STATE : ACTIVE
97
+ EXECUTION MODE : PRIORITY
98
+ MAX CONCURRENCY : 3
99
+ IDLE TIMEOUT SEC : 5000
100
+ CREATED AT : 2025-04-15 20:40:44
101
+ CREATOR ID : usr_we8x7d7u8hq8mj2488ed9x47n6
102
+ CREATOR EMAIL : test@anyscale.com
103
+ COMPUTE CONFIG ID : cpt_8hzsv1t4jvb6kwjhfqbfjw5i6b
104
+ CURRENT CLUSTER STATE : Terminated
105
+ CLUSTER ID : ses_cjr7uaf1yh2ue5uzvd11p24p4u
106
+ PROJECT ID : prj_7FWKGPGPaD3Q5mvk9zK2viBD
107
+ CLOUD ID : cld_kvedZWag2qA8i5BjxUevf5i7
108
+ TOTAL JOBS : 6
109
+ SUCCESSFUL JOBS : 6
110
+ FAILED JOBS : 0
111
+ ACTIVE JOBS : 0
112
+ """
113
+
114
+ JOB_QUEUE_UPDATE = """\
115
+ $ anyscale job-queue update --id jq_h8fcze2qkr8wttuuvapi1hvyuc --max-concurrency 5
116
+ Output
117
+ ID : jq_h8fcze2qkr8wttuuvapi1hvyuc
118
+ USER PROVIDED ID : queue_3
119
+ NAME : queue_3
120
+ CURRENT JOB QUEUE STATE : ACTIVE
121
+ EXECUTION MODE : PRIORITY
122
+ MAX CONCURRENCY : 5
123
+ IDLE TIMEOUT SEC : 5000
124
+ CREATED AT : 2025-04-15 20:40:44
125
+ CREATOR ID : usr_we8x7d7u8hq8mj2488ed9x47n6
126
+ CREATOR EMAIL : test@anyscale.com
127
+ COMPUTE CONFIG ID : cpt_8hzsv1t4jvb6kwjhfqbfjw5i6b
128
+ CURRENT CLUSTER STATE : Terminated
129
+ CLUSTER ID : ses_cjr7uaf1yh2ue5uzvd11p24p4u
130
+ PROJECT ID : prj_7FWKGPGPaD3Q5mvk9zK2viBD
131
+ CLOUD ID : cld_kvedZWag2qA8i5BjxUevf5i7
132
+ TOTAL JOBS : 6
133
+ SUCCESSFUL JOBS : 6
134
+ FAILED JOBS : 0
135
+ ACTIVE JOBS : 0
136
+ """
137
+
80
138
  SCHEDULE_APPLY_EXAMPLE = """\
81
139
  $ anyscale schedule apply -n my-schedule -f my-schedule.yaml
82
140
  (anyscale +0.5s) Applying schedule with config ScheduleConfig(job_config=JobConfig(name='my-schedule', image_uri=None, compute_config=None, env_vars=None, py_modules=None, cloud=None, project=None, ray_version=None, job_queue_config=None), cron_expression='0 0 * * * *', timezone='UTC').
@@ -396,14 +396,14 @@ and override the entrypoint with `python main.py`.
396
396
  help=f"Filter jobs by state. Accepts one or more states. Allowed states: {', '.join(HaJobStates.allowable_values)}",
397
397
  callback=validate_list_jobs_state_filter,
398
398
  )
399
- def list( # noqa: A001
399
+ def list( # noqa: A001 PLR0913
400
400
  name: Optional[str],
401
401
  id: Optional[str], # noqa: A002
402
402
  project_id: Optional[str],
403
403
  include_all_users: bool,
404
404
  include_archived: bool,
405
405
  max_items: int,
406
- states: List[str],
406
+ states: List[HaJobStates],
407
407
  ) -> None:
408
408
  job_controller = JobController()
409
409
  job_controller.list(
@@ -0,0 +1,172 @@
1
+ from typing import List
2
+
3
+ import click
4
+
5
+ from anyscale.client.openapi_client.models.job_queue_sort_directive import (
6
+ JobQueueSortDirective,
7
+ )
8
+ from anyscale.client.openapi_client.models.job_queue_sort_field import JobQueueSortField
9
+ from anyscale.client.openapi_client.models.sort_order import SortOrder
10
+ from anyscale.commands import command_examples
11
+ from anyscale.commands.util import AnyscaleCommand
12
+ from anyscale.controllers.job_controller import JobController, JobQueueView
13
+ from anyscale.util import validate_non_negative_arg
14
+
15
+
16
+ @click.group(
17
+ "job-queues", help="Interact with production job queues running on Anyscale."
18
+ )
19
+ def job_queue_cli() -> None:
20
+ pass
21
+
22
+
23
+ def parse_sort_fields(
24
+ param: str, sort_fields: List[str],
25
+ ) -> List[JobQueueSortDirective]:
26
+ sort_directives = []
27
+
28
+ for field_str in sort_fields:
29
+ descending = field_str.startswith("-")
30
+ raw_field = field_str.lstrip("-").upper()
31
+
32
+ if raw_field not in JobQueueSortField.allowable_values:
33
+ raise click.UsageError(
34
+ f"{param} must be one of {', '.join([v.lower() for v in JobQueueSortField.allowable_values])}"
35
+ )
36
+
37
+ sort_directives.append(
38
+ JobQueueSortDirective(
39
+ sort_field=raw_field,
40
+ sort_order=SortOrder.DESC if descending else SortOrder.ASC,
41
+ )
42
+ )
43
+
44
+ return sort_directives
45
+
46
+
47
+ @job_queue_cli.command(
48
+ name="list",
49
+ short_help="List job queues.",
50
+ cls=AnyscaleCommand,
51
+ example=command_examples.JOB_QUEUE_LIST,
52
+ )
53
+ @click.option(
54
+ "--include-all-users",
55
+ is_flag=True,
56
+ default=False,
57
+ help="Include job queues not created by current user.",
58
+ )
59
+ @click.option(
60
+ "--view",
61
+ type=click.Choice([v.name.lower() for v in JobQueueView], case_sensitive=False),
62
+ default=JobQueueView.DEFAULT.name,
63
+ help="Select which view to display.",
64
+ callback=lambda _, __, value: JobQueueView[value.upper()],
65
+ )
66
+ @click.option(
67
+ "--page",
68
+ default=100,
69
+ type=int,
70
+ help="Page size (default 100).",
71
+ callback=validate_non_negative_arg,
72
+ )
73
+ @click.option(
74
+ "--max-items",
75
+ required=False,
76
+ type=int,
77
+ help="Max items to show in list (only valid in interactive mode).",
78
+ callback=lambda ctx, param, value: validate_non_negative_arg(ctx, param, value)
79
+ if value
80
+ else None,
81
+ )
82
+ @click.option(
83
+ "--sort",
84
+ "sorting_directives",
85
+ multiple=True,
86
+ default=[JobQueueSortField.CREATED_AT],
87
+ help=f"""
88
+ Sort by column(s). Prefix column with - to sort in descending order.
89
+ Supported columns: {', '.join([v.lower() for v in JobQueueSortField.allowable_values])}.
90
+ """,
91
+ callback=lambda _, __, value: parse_sort_fields("sort", list(value)),
92
+ )
93
+ @click.option(
94
+ "--interactive/--no-interactive",
95
+ default=True,
96
+ help="--no-interactive disables the default interactive mode.",
97
+ )
98
+ def list_job_queues(
99
+ include_all_users: bool,
100
+ view: JobQueueView,
101
+ page: int,
102
+ max_items: int,
103
+ sorting_directives: List[JobQueueSortDirective],
104
+ interactive: bool,
105
+ ):
106
+ if max_items is not None and interactive:
107
+ raise click.UsageError("--max-items can only be used in non interactive mode.")
108
+ job_controller = JobController()
109
+ job_controller.list_job_queues(
110
+ max_items=max_items,
111
+ page_size=page,
112
+ include_all_users=include_all_users,
113
+ view=view,
114
+ sorting_directives=sorting_directives,
115
+ interactive=interactive,
116
+ )
117
+
118
+
119
+ @job_queue_cli.command(
120
+ name="update",
121
+ short_help="Update job queue.",
122
+ cls=AnyscaleCommand,
123
+ example=command_examples.JOB_QUEUE_UPDATE,
124
+ )
125
+ @click.option(
126
+ "--id", "job_queue_id", required=False, default=None, help="ID of the job queue."
127
+ )
128
+ @click.option(
129
+ "--name",
130
+ "job_queue_name",
131
+ required=False,
132
+ default=None,
133
+ help="Name of the job queue.",
134
+ )
135
+ @click.option(
136
+ "--max-concurrency",
137
+ required=False,
138
+ default=None,
139
+ help="Maximum concurrency of the job queue",
140
+ )
141
+ @click.option(
142
+ "--idle-timeout-s",
143
+ required=False,
144
+ default=None,
145
+ help="Idle timeout of the job queue",
146
+ )
147
+ def update_job_queue(
148
+ job_queue_id: str, job_queue_name: str, max_concurrency: int, idle_timeout_s: int
149
+ ):
150
+ if job_queue_id is None and job_queue_name is None:
151
+ raise click.ClickException("ID or name of job queue is required")
152
+ job_controller = JobController()
153
+ job_controller.update_job_queue(
154
+ job_queue_id=job_queue_id,
155
+ job_queue_name=job_queue_name,
156
+ max_concurrency=max_concurrency,
157
+ idle_timeout_s=idle_timeout_s,
158
+ )
159
+
160
+
161
+ @job_queue_cli.command(
162
+ name="info",
163
+ short_help="Info of a job queue.",
164
+ cls=AnyscaleCommand,
165
+ example=command_examples.JOB_QUEUE_INFO,
166
+ )
167
+ @click.option(
168
+ "--id", "job_queue_id", required=True, default=None, help="ID of the job."
169
+ )
170
+ def get_job_queue(job_queue_id: str):
171
+ job_controller = JobController()
172
+ job_controller.get_job_queue(job_queue_id=job_queue_id)