anyscale 0.26.61__py3-none-any.whl → 0.26.63__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.
- anyscale/_private/anyscale_client/anyscale_client.py +4 -1
- anyscale/_private/docgen/__main__.py +0 -2
- anyscale/_private/docgen/models.md +2 -0
- anyscale/client/README.md +17 -3
- anyscale/client/openapi_client/__init__.py +10 -3
- anyscale/client/openapi_client/api/default_api.py +3229 -2400
- anyscale/client/openapi_client/models/__init__.py +10 -3
- anyscale/client/openapi_client/models/api_key_info.py +280 -0
- anyscale/client/openapi_client/models/api_key_parameters.py +29 -3
- anyscale/client/openapi_client/models/{aggregatedinstanceusagecsv_list_response.py → apikeyinfo_list_response.py} +15 -15
- anyscale/client/openapi_client/models/compute_node_type.py +29 -1
- anyscale/client/openapi_client/models/gpu_usage.py +236 -0
- anyscale/client/openapi_client/models/node_metrics.py +404 -0
- anyscale/client/openapi_client/models/node_metrics_response.py +123 -0
- anyscale/client/openapi_client/models/nodemetricsresponse_response.py +121 -0
- anyscale/client/openapi_client/models/operator_metrics.py +27 -1
- anyscale/client/openapi_client/models/revoke_api_keys_request.py +123 -0
- anyscale/client/openapi_client/models/revoke_api_keys_response.py +202 -0
- anyscale/client/openapi_client/models/revokeapikeysresponse_response.py +121 -0
- anyscale/client/openapi_client/models/{cloud_hosting_type.py → task_summary_config.py} +33 -13
- anyscale/client/openapi_client/models/task_table_config.py +29 -3
- anyscale/client/openapi_client/models/task_table_row.py +29 -3
- anyscale/client/openapi_client/models/worker_node_type.py +29 -1
- anyscale/commands/cloud_commands.py +146 -61
- anyscale/commands/command_examples.py +12 -0
- anyscale/commands/service_account_commands.py +0 -21
- anyscale/compute_config/_private/compute_config_sdk.py +4 -0
- anyscale/compute_config/models.py +24 -0
- anyscale/controllers/cloud_controller.py +94 -20
- anyscale/sdk/anyscale_client/models/compute_node_type.py +29 -1
- anyscale/sdk/anyscale_client/models/worker_node_type.py +29 -1
- anyscale/service_account/_private/service_account_sdk.py +10 -1
- anyscale/version.py +1 -1
- anyscale/workspace/commands.py +23 -114
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/METADATA +1 -1
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/RECORD +41 -34
- anyscale/client/openapi_client/models/aggregated_instance_usage_csv.py +0 -889
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/WHEEL +0 -0
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/licenses/LICENSE +0 -0
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/licenses/NOTICE +0 -0
- {anyscale-0.26.61.dist-info → anyscale-0.26.63.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,121 @@
|
|
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 RevokeapikeysresponseResponse(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
|
+
'result': 'RevokeApiKeysResponse'
|
37
|
+
}
|
38
|
+
|
39
|
+
attribute_map = {
|
40
|
+
'result': 'result'
|
41
|
+
}
|
42
|
+
|
43
|
+
def __init__(self, result=None, local_vars_configuration=None): # noqa: E501
|
44
|
+
"""RevokeapikeysresponseResponse - a model defined in OpenAPI""" # noqa: E501
|
45
|
+
if local_vars_configuration is None:
|
46
|
+
local_vars_configuration = Configuration()
|
47
|
+
self.local_vars_configuration = local_vars_configuration
|
48
|
+
|
49
|
+
self._result = None
|
50
|
+
self.discriminator = None
|
51
|
+
|
52
|
+
self.result = result
|
53
|
+
|
54
|
+
@property
|
55
|
+
def result(self):
|
56
|
+
"""Gets the result of this RevokeapikeysresponseResponse. # noqa: E501
|
57
|
+
|
58
|
+
|
59
|
+
:return: The result of this RevokeapikeysresponseResponse. # noqa: E501
|
60
|
+
:rtype: RevokeApiKeysResponse
|
61
|
+
"""
|
62
|
+
return self._result
|
63
|
+
|
64
|
+
@result.setter
|
65
|
+
def result(self, result):
|
66
|
+
"""Sets the result of this RevokeapikeysresponseResponse.
|
67
|
+
|
68
|
+
|
69
|
+
:param result: The result of this RevokeapikeysresponseResponse. # noqa: E501
|
70
|
+
:type: RevokeApiKeysResponse
|
71
|
+
"""
|
72
|
+
if self.local_vars_configuration.client_side_validation and result is None: # noqa: E501
|
73
|
+
raise ValueError("Invalid value for `result`, must not be `None`") # noqa: E501
|
74
|
+
|
75
|
+
self._result = result
|
76
|
+
|
77
|
+
def to_dict(self):
|
78
|
+
"""Returns the model properties as a dict"""
|
79
|
+
result = {}
|
80
|
+
|
81
|
+
for attr, _ in six.iteritems(self.openapi_types):
|
82
|
+
value = getattr(self, attr)
|
83
|
+
if isinstance(value, list):
|
84
|
+
result[attr] = list(map(
|
85
|
+
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
|
86
|
+
value
|
87
|
+
))
|
88
|
+
elif hasattr(value, "to_dict"):
|
89
|
+
result[attr] = value.to_dict()
|
90
|
+
elif isinstance(value, dict):
|
91
|
+
result[attr] = dict(map(
|
92
|
+
lambda item: (item[0], item[1].to_dict())
|
93
|
+
if hasattr(item[1], "to_dict") else item,
|
94
|
+
value.items()
|
95
|
+
))
|
96
|
+
else:
|
97
|
+
result[attr] = value
|
98
|
+
|
99
|
+
return result
|
100
|
+
|
101
|
+
def to_str(self):
|
102
|
+
"""Returns the string representation of the model"""
|
103
|
+
return pprint.pformat(self.to_dict())
|
104
|
+
|
105
|
+
def __repr__(self):
|
106
|
+
"""For `print` and `pprint`"""
|
107
|
+
return self.to_str()
|
108
|
+
|
109
|
+
def __eq__(self, other):
|
110
|
+
"""Returns true if both objects are equal"""
|
111
|
+
if not isinstance(other, RevokeapikeysresponseResponse):
|
112
|
+
return False
|
113
|
+
|
114
|
+
return self.to_dict() == other.to_dict()
|
115
|
+
|
116
|
+
def __ne__(self, other):
|
117
|
+
"""Returns true if both objects are not equal"""
|
118
|
+
if not isinstance(other, RevokeapikeysresponseResponse):
|
119
|
+
return True
|
120
|
+
|
121
|
+
return self.to_dict() != other.to_dict()
|
@@ -18,21 +18,13 @@ import six
|
|
18
18
|
from openapi_client.configuration import Configuration
|
19
19
|
|
20
20
|
|
21
|
-
class
|
21
|
+
class TaskSummaryConfig(object):
|
22
22
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
23
23
|
Ref: https://openapi-generator.tech
|
24
24
|
|
25
25
|
Do not edit the class manually.
|
26
26
|
"""
|
27
27
|
|
28
|
-
"""
|
29
|
-
allowed enum values
|
30
|
-
"""
|
31
|
-
ANYSCALE_HOSTED = "anyscale_hosted"
|
32
|
-
CUSTOMER_HOSTED = "customer_hosted"
|
33
|
-
|
34
|
-
allowable_values = [ANYSCALE_HOSTED, CUSTOMER_HOSTED] # noqa: E501
|
35
|
-
|
36
28
|
"""
|
37
29
|
Attributes:
|
38
30
|
openapi_types (dict): The key is attribute name
|
@@ -41,18 +33,46 @@ class CloudHostingType(object):
|
|
41
33
|
and the value is json key in definition.
|
42
34
|
"""
|
43
35
|
openapi_types = {
|
36
|
+
'data_operator_id': 'str'
|
44
37
|
}
|
45
38
|
|
46
39
|
attribute_map = {
|
40
|
+
'data_operator_id': 'data_operator_id'
|
47
41
|
}
|
48
42
|
|
49
|
-
def __init__(self, local_vars_configuration=None): # noqa: E501
|
50
|
-
"""
|
43
|
+
def __init__(self, data_operator_id=None, local_vars_configuration=None): # noqa: E501
|
44
|
+
"""TaskSummaryConfig - a model defined in OpenAPI""" # noqa: E501
|
51
45
|
if local_vars_configuration is None:
|
52
46
|
local_vars_configuration = Configuration()
|
53
47
|
self.local_vars_configuration = local_vars_configuration
|
48
|
+
|
49
|
+
self._data_operator_id = None
|
54
50
|
self.discriminator = None
|
55
51
|
|
52
|
+
if data_operator_id is not None:
|
53
|
+
self.data_operator_id = data_operator_id
|
54
|
+
|
55
|
+
@property
|
56
|
+
def data_operator_id(self):
|
57
|
+
"""Gets the data_operator_id of this TaskSummaryConfig. # noqa: E501
|
58
|
+
|
59
|
+
|
60
|
+
:return: The data_operator_id of this TaskSummaryConfig. # noqa: E501
|
61
|
+
:rtype: str
|
62
|
+
"""
|
63
|
+
return self._data_operator_id
|
64
|
+
|
65
|
+
@data_operator_id.setter
|
66
|
+
def data_operator_id(self, data_operator_id):
|
67
|
+
"""Sets the data_operator_id of this TaskSummaryConfig.
|
68
|
+
|
69
|
+
|
70
|
+
:param data_operator_id: The data_operator_id of this TaskSummaryConfig. # noqa: E501
|
71
|
+
:type: str
|
72
|
+
"""
|
73
|
+
|
74
|
+
self._data_operator_id = data_operator_id
|
75
|
+
|
56
76
|
def to_dict(self):
|
57
77
|
"""Returns the model properties as a dict"""
|
58
78
|
result = {}
|
@@ -87,14 +107,14 @@ class CloudHostingType(object):
|
|
87
107
|
|
88
108
|
def __eq__(self, other):
|
89
109
|
"""Returns true if both objects are equal"""
|
90
|
-
if not isinstance(other,
|
110
|
+
if not isinstance(other, TaskSummaryConfig):
|
91
111
|
return False
|
92
112
|
|
93
113
|
return self.to_dict() == other.to_dict()
|
94
114
|
|
95
115
|
def __ne__(self, other):
|
96
116
|
"""Returns true if both objects are not equal"""
|
97
|
-
if not isinstance(other,
|
117
|
+
if not isinstance(other, TaskSummaryConfig):
|
98
118
|
return True
|
99
119
|
|
100
120
|
return self.to_dict() != other.to_dict()
|
@@ -39,7 +39,8 @@ class TaskTableConfig(object):
|
|
39
39
|
'text': 'str',
|
40
40
|
'job_id': 'str',
|
41
41
|
'exception_type': 'str',
|
42
|
-
'attempts': 'TaskAttempts'
|
42
|
+
'attempts': 'TaskAttempts',
|
43
|
+
'data_operator_id': 'str'
|
43
44
|
}
|
44
45
|
|
45
46
|
attribute_map = {
|
@@ -49,10 +50,11 @@ class TaskTableConfig(object):
|
|
49
50
|
'text': 'text',
|
50
51
|
'job_id': 'job_id',
|
51
52
|
'exception_type': 'exception_type',
|
52
|
-
'attempts': 'attempts'
|
53
|
+
'attempts': 'attempts',
|
54
|
+
'data_operator_id': 'data_operator_id'
|
53
55
|
}
|
54
56
|
|
55
|
-
def __init__(self, task_id=None, function_name=None, current_state=None, text=None, job_id=None, exception_type=None, attempts=None, local_vars_configuration=None): # noqa: E501
|
57
|
+
def __init__(self, task_id=None, function_name=None, current_state=None, text=None, job_id=None, exception_type=None, attempts=None, data_operator_id=None, local_vars_configuration=None): # noqa: E501
|
56
58
|
"""TaskTableConfig - a model defined in OpenAPI""" # noqa: E501
|
57
59
|
if local_vars_configuration is None:
|
58
60
|
local_vars_configuration = Configuration()
|
@@ -65,6 +67,7 @@ class TaskTableConfig(object):
|
|
65
67
|
self._job_id = None
|
66
68
|
self._exception_type = None
|
67
69
|
self._attempts = None
|
70
|
+
self._data_operator_id = None
|
68
71
|
self.discriminator = None
|
69
72
|
|
70
73
|
if task_id is not None:
|
@@ -81,6 +84,8 @@ class TaskTableConfig(object):
|
|
81
84
|
self.exception_type = exception_type
|
82
85
|
if attempts is not None:
|
83
86
|
self.attempts = attempts
|
87
|
+
if data_operator_id is not None:
|
88
|
+
self.data_operator_id = data_operator_id
|
84
89
|
|
85
90
|
@property
|
86
91
|
def task_id(self):
|
@@ -229,6 +234,27 @@ class TaskTableConfig(object):
|
|
229
234
|
|
230
235
|
self._attempts = attempts
|
231
236
|
|
237
|
+
@property
|
238
|
+
def data_operator_id(self):
|
239
|
+
"""Gets the data_operator_id of this TaskTableConfig. # noqa: E501
|
240
|
+
|
241
|
+
|
242
|
+
:return: The data_operator_id of this TaskTableConfig. # noqa: E501
|
243
|
+
:rtype: str
|
244
|
+
"""
|
245
|
+
return self._data_operator_id
|
246
|
+
|
247
|
+
@data_operator_id.setter
|
248
|
+
def data_operator_id(self, data_operator_id):
|
249
|
+
"""Sets the data_operator_id of this TaskTableConfig.
|
250
|
+
|
251
|
+
|
252
|
+
:param data_operator_id: The data_operator_id of this TaskTableConfig. # noqa: E501
|
253
|
+
:type: str
|
254
|
+
"""
|
255
|
+
|
256
|
+
self._data_operator_id = data_operator_id
|
257
|
+
|
232
258
|
def to_dict(self):
|
233
259
|
"""Returns the model properties as a dict"""
|
234
260
|
result = {}
|
@@ -51,7 +51,8 @@ class TaskTableRow(object):
|
|
51
51
|
'worker_pid': 'str',
|
52
52
|
'parent_task_id': 'str',
|
53
53
|
'ray_session_name': 'str',
|
54
|
-
'exception_type': 'str'
|
54
|
+
'exception_type': 'str',
|
55
|
+
'data_operator_id': 'str'
|
55
56
|
}
|
56
57
|
|
57
58
|
attribute_map = {
|
@@ -73,10 +74,11 @@ class TaskTableRow(object):
|
|
73
74
|
'worker_pid': 'worker_pid',
|
74
75
|
'parent_task_id': 'parent_task_id',
|
75
76
|
'ray_session_name': 'ray_session_name',
|
76
|
-
'exception_type': 'exception_type'
|
77
|
+
'exception_type': 'exception_type',
|
78
|
+
'data_operator_id': 'data_operator_id'
|
77
79
|
}
|
78
80
|
|
79
|
-
def __init__(self, id=None, attempt_number=None, total_attempts=None, job_id=None, function_name=None, task_type=None, current_state=None, error_message=None, start_time_ns=None, start_running_time_ns=None, end_time_ns=None, required_resources=None, runtime_env=None, node_id=None, worker_id=None, worker_pid=None, parent_task_id=None, ray_session_name=None, exception_type=None, local_vars_configuration=None): # noqa: E501
|
81
|
+
def __init__(self, id=None, attempt_number=None, total_attempts=None, job_id=None, function_name=None, task_type=None, current_state=None, error_message=None, start_time_ns=None, start_running_time_ns=None, end_time_ns=None, required_resources=None, runtime_env=None, node_id=None, worker_id=None, worker_pid=None, parent_task_id=None, ray_session_name=None, exception_type=None, data_operator_id=None, local_vars_configuration=None): # noqa: E501
|
80
82
|
"""TaskTableRow - a model defined in OpenAPI""" # noqa: E501
|
81
83
|
if local_vars_configuration is None:
|
82
84
|
local_vars_configuration = Configuration()
|
@@ -101,6 +103,7 @@ class TaskTableRow(object):
|
|
101
103
|
self._parent_task_id = None
|
102
104
|
self._ray_session_name = None
|
103
105
|
self._exception_type = None
|
106
|
+
self._data_operator_id = None
|
104
107
|
self.discriminator = None
|
105
108
|
|
106
109
|
self.id = id
|
@@ -133,6 +136,8 @@ class TaskTableRow(object):
|
|
133
136
|
self.ray_session_name = ray_session_name
|
134
137
|
if exception_type is not None:
|
135
138
|
self.exception_type = exception_type
|
139
|
+
if data_operator_id is not None:
|
140
|
+
self.data_operator_id = data_operator_id
|
136
141
|
|
137
142
|
@property
|
138
143
|
def id(self):
|
@@ -549,6 +554,27 @@ class TaskTableRow(object):
|
|
549
554
|
|
550
555
|
self._exception_type = exception_type
|
551
556
|
|
557
|
+
@property
|
558
|
+
def data_operator_id(self):
|
559
|
+
"""Gets the data_operator_id of this TaskTableRow. # noqa: E501
|
560
|
+
|
561
|
+
|
562
|
+
:return: The data_operator_id of this TaskTableRow. # noqa: E501
|
563
|
+
:rtype: str
|
564
|
+
"""
|
565
|
+
return self._data_operator_id
|
566
|
+
|
567
|
+
@data_operator_id.setter
|
568
|
+
def data_operator_id(self, data_operator_id):
|
569
|
+
"""Sets the data_operator_id of this TaskTableRow.
|
570
|
+
|
571
|
+
|
572
|
+
:param data_operator_id: The data_operator_id of this TaskTableRow. # noqa: E501
|
573
|
+
:type: str
|
574
|
+
"""
|
575
|
+
|
576
|
+
self._data_operator_id = data_operator_id
|
577
|
+
|
552
578
|
def to_dict(self):
|
553
579
|
"""Returns the model properties as a dict"""
|
554
580
|
result = {}
|
@@ -36,6 +36,7 @@ class WorkerNodeType(object):
|
|
36
36
|
'name': 'str',
|
37
37
|
'instance_type': 'str',
|
38
38
|
'resources': 'Resources',
|
39
|
+
'labels': 'dict(str, str)',
|
39
40
|
'aws_advanced_configurations_json': 'object',
|
40
41
|
'gcp_advanced_configurations_json': 'object',
|
41
42
|
'advanced_configurations_json': 'object',
|
@@ -50,6 +51,7 @@ class WorkerNodeType(object):
|
|
50
51
|
'name': 'name',
|
51
52
|
'instance_type': 'instance_type',
|
52
53
|
'resources': 'resources',
|
54
|
+
'labels': 'labels',
|
53
55
|
'aws_advanced_configurations_json': 'aws_advanced_configurations_json',
|
54
56
|
'gcp_advanced_configurations_json': 'gcp_advanced_configurations_json',
|
55
57
|
'advanced_configurations_json': 'advanced_configurations_json',
|
@@ -60,7 +62,7 @@ class WorkerNodeType(object):
|
|
60
62
|
'fallback_to_ondemand': 'fallback_to_ondemand'
|
61
63
|
}
|
62
64
|
|
63
|
-
def __init__(self, name=None, instance_type=None, resources=None, aws_advanced_configurations_json=None, gcp_advanced_configurations_json=None, advanced_configurations_json=None, flags=None, min_workers=None, max_workers=None, use_spot=False, fallback_to_ondemand=False, local_vars_configuration=None): # noqa: E501
|
65
|
+
def __init__(self, name=None, instance_type=None, resources=None, labels=None, aws_advanced_configurations_json=None, gcp_advanced_configurations_json=None, advanced_configurations_json=None, flags=None, min_workers=None, max_workers=None, use_spot=False, fallback_to_ondemand=False, local_vars_configuration=None): # noqa: E501
|
64
66
|
"""WorkerNodeType - a model defined in OpenAPI""" # noqa: E501
|
65
67
|
if local_vars_configuration is None:
|
66
68
|
local_vars_configuration = Configuration()
|
@@ -69,6 +71,7 @@ class WorkerNodeType(object):
|
|
69
71
|
self._name = None
|
70
72
|
self._instance_type = None
|
71
73
|
self._resources = None
|
74
|
+
self._labels = None
|
72
75
|
self._aws_advanced_configurations_json = None
|
73
76
|
self._gcp_advanced_configurations_json = None
|
74
77
|
self._advanced_configurations_json = None
|
@@ -83,6 +86,8 @@ class WorkerNodeType(object):
|
|
83
86
|
self.instance_type = instance_type
|
84
87
|
if resources is not None:
|
85
88
|
self.resources = resources
|
89
|
+
if labels is not None:
|
90
|
+
self.labels = labels
|
86
91
|
if aws_advanced_configurations_json is not None:
|
87
92
|
self.aws_advanced_configurations_json = aws_advanced_configurations_json
|
88
93
|
if gcp_advanced_configurations_json is not None:
|
@@ -173,6 +178,29 @@ class WorkerNodeType(object):
|
|
173
178
|
|
174
179
|
self._resources = resources
|
175
180
|
|
181
|
+
@property
|
182
|
+
def labels(self):
|
183
|
+
"""Gets the labels of this WorkerNodeType. # noqa: E501
|
184
|
+
|
185
|
+
Labels to associate the node with for scheduling purposes. Defaults to the list of Ray & Anyscale default labels. # noqa: E501
|
186
|
+
|
187
|
+
:return: The labels of this WorkerNodeType. # noqa: E501
|
188
|
+
:rtype: dict(str, str)
|
189
|
+
"""
|
190
|
+
return self._labels
|
191
|
+
|
192
|
+
@labels.setter
|
193
|
+
def labels(self, labels):
|
194
|
+
"""Sets the labels of this WorkerNodeType.
|
195
|
+
|
196
|
+
Labels to associate the node with for scheduling purposes. Defaults to the list of Ray & Anyscale default labels. # noqa: E501
|
197
|
+
|
198
|
+
:param labels: The labels of this WorkerNodeType. # noqa: E501
|
199
|
+
:type: dict(str, str)
|
200
|
+
"""
|
201
|
+
|
202
|
+
self._labels = labels
|
203
|
+
|
176
204
|
@property
|
177
205
|
def aws_advanced_configurations_json(self):
|
178
206
|
"""Gets the aws_advanced_configurations_json of this WorkerNodeType. # noqa: E501
|
@@ -433,22 +433,130 @@ def cloud_update( # noqa: PLR0913
|
|
433
433
|
help="Cloud id to get details about. Alternative to cloud name.",
|
434
434
|
required=False,
|
435
435
|
)
|
436
|
+
@click.option(
|
437
|
+
"--resource",
|
438
|
+
help="Name of the cloud resource to get details for. If not provided, defaults to the primary resource for the cloud.",
|
439
|
+
type=str,
|
440
|
+
required=False,
|
441
|
+
)
|
442
|
+
@click.option(
|
443
|
+
"--resource-id",
|
444
|
+
"cloud_resource_id",
|
445
|
+
help="Cloud resource ID to get details for. Alternative to cloud resource name.",
|
446
|
+
type=str,
|
447
|
+
required=False,
|
448
|
+
)
|
436
449
|
def cloud_config_get(
|
437
|
-
cloud_name: Optional[str],
|
450
|
+
cloud_name: Optional[str],
|
451
|
+
name: Optional[str],
|
452
|
+
cloud_id: Optional[str],
|
453
|
+
resource: Optional[str],
|
454
|
+
cloud_resource_id: Optional[str],
|
438
455
|
) -> None:
|
439
456
|
if cloud_name and name and cloud_name != name:
|
440
457
|
raise click.ClickException(
|
441
458
|
"The positional argument CLOUD_NAME and the keyword argument --name "
|
442
459
|
"were both provided. Please only provide one of these two arguments."
|
443
460
|
)
|
461
|
+
|
462
|
+
# Validate resource selection options
|
463
|
+
if resource and cloud_resource_id:
|
464
|
+
raise click.ClickException(
|
465
|
+
"Cannot specify both --resource and --resource-id. Please provide only one."
|
466
|
+
)
|
467
|
+
|
444
468
|
config = CloudController().get_cloud_config(
|
445
|
-
cloud_name=cloud_name or name,
|
469
|
+
cloud_name=cloud_name or name,
|
470
|
+
cloud_id=cloud_id,
|
471
|
+
resource=resource,
|
472
|
+
cloud_resource_id=cloud_resource_id,
|
446
473
|
)
|
447
474
|
stream = StringIO()
|
448
475
|
yaml.dump(config.spec, stream)
|
449
476
|
print(stream.getvalue())
|
450
477
|
|
451
478
|
|
479
|
+
def _validate_cloud_config_update_args(
|
480
|
+
cloud_name: Optional[str],
|
481
|
+
name: Optional[str],
|
482
|
+
resource: Optional[str],
|
483
|
+
cloud_resource_id: Optional[str],
|
484
|
+
passed_enable_disable_flags: bool,
|
485
|
+
spec_file: Optional[str],
|
486
|
+
) -> None:
|
487
|
+
"""Validate arguments for cloud config update command."""
|
488
|
+
if cloud_name and name and cloud_name != name:
|
489
|
+
raise click.ClickException(
|
490
|
+
"The positional argument CLOUD_NAME and the keyword argument --name "
|
491
|
+
"were both provided. Please only provide one of these two arguments."
|
492
|
+
)
|
493
|
+
|
494
|
+
if resource and cloud_resource_id:
|
495
|
+
raise click.ClickException(
|
496
|
+
"Cannot specify both --resource and --resource-id. Please provide only one."
|
497
|
+
)
|
498
|
+
|
499
|
+
if passed_enable_disable_flags and spec_file:
|
500
|
+
raise click.ClickException(
|
501
|
+
"Invalid combination of arguments: --spec-file should not be provided with any other enable/disable flags."
|
502
|
+
)
|
503
|
+
|
504
|
+
if (resource or cloud_resource_id) and not spec_file:
|
505
|
+
raise click.ClickException(
|
506
|
+
"--resource and --resource-id can only be used with --spec-file."
|
507
|
+
)
|
508
|
+
|
509
|
+
|
510
|
+
def _handle_log_ingestion_config(enable_log_ingestion: Optional[bool]) -> None:
|
511
|
+
"""Handle log ingestion configuration with user prompts."""
|
512
|
+
if enable_log_ingestion is True:
|
513
|
+
consent_message = click.prompt(
|
514
|
+
"--enable-log-ingestion is specified. Please note the logs produced by "
|
515
|
+
"your cluster will be ingested into Anyscale's service in region "
|
516
|
+
"us-west-2. Your clusters may incur extra data transfer cost from the "
|
517
|
+
"cloud provider. If you are sure you want to enable this feature, "
|
518
|
+
'please type "consent"',
|
519
|
+
type=str,
|
520
|
+
)
|
521
|
+
if consent_message != "consent":
|
522
|
+
raise click.ClickException(
|
523
|
+
'You must type "consent" to enable log ingestion.'
|
524
|
+
)
|
525
|
+
elif enable_log_ingestion is False:
|
526
|
+
confirm_response = click.confirm(
|
527
|
+
"--disable-log-ingestion is specified. Please note the logs that's "
|
528
|
+
"already ingested will not be deleted. Existing clusters will not stop"
|
529
|
+
"the log ingestion until you restart them. Logs are automatically "
|
530
|
+
"deleted after 30 days from the time of ingestion. Are you sure you "
|
531
|
+
"want to disable log ingestion?"
|
532
|
+
)
|
533
|
+
if not confirm_response:
|
534
|
+
raise click.ClickException("You must confirm to disable log ingestion.")
|
535
|
+
|
536
|
+
|
537
|
+
def _handle_system_cluster_config(enable_system_cluster: Optional[bool]) -> None:
|
538
|
+
"""Handle system cluster configuration with user prompts."""
|
539
|
+
confirm_response = True
|
540
|
+
if enable_system_cluster is True:
|
541
|
+
confirm_response = click.confirm(
|
542
|
+
"--enable-system-cluster is specified. Please note that this will enable "
|
543
|
+
"system cluster functionality for the cloud and will incur extra cost. "
|
544
|
+
"Are you sure you want to enable system cluster?"
|
545
|
+
)
|
546
|
+
elif enable_system_cluster is False:
|
547
|
+
confirm_response = click.confirm(
|
548
|
+
"--disable-system-cluster is specified. This will disable system cluster "
|
549
|
+
"functionality for the cloud. Please note that this will not terminate "
|
550
|
+
"the system cluster if it is currently running. "
|
551
|
+
"Are you sure you want to disable system cluster?"
|
552
|
+
)
|
553
|
+
|
554
|
+
if enable_system_cluster is not None and not confirm_response:
|
555
|
+
raise click.ClickException(
|
556
|
+
f"You must confirm to {'enable' if enable_system_cluster else 'disable'} system cluster."
|
557
|
+
)
|
558
|
+
|
559
|
+
|
452
560
|
@cloud_config_group.command(
|
453
561
|
"update",
|
454
562
|
help="Update the current configuration for a cloud.",
|
@@ -490,88 +598,65 @@ def cloud_config_get(
|
|
490
598
|
required=False,
|
491
599
|
help="Provide a path to a specification file.",
|
492
600
|
)
|
493
|
-
|
601
|
+
@click.option(
|
602
|
+
"--resource",
|
603
|
+
help="Name of the cloud resource to get details for. If not provided, defaults to the primary resource for the cloud.",
|
604
|
+
type=str,
|
605
|
+
required=False,
|
606
|
+
)
|
607
|
+
@click.option(
|
608
|
+
"--resource-id",
|
609
|
+
"cloud_resource_id",
|
610
|
+
help="Cloud resource ID to get details for. Alternative to cloud resource name.",
|
611
|
+
type=str,
|
612
|
+
required=False,
|
613
|
+
)
|
614
|
+
def cloud_config_update( # noqa: PLR0913
|
494
615
|
cloud_name: Optional[str],
|
495
616
|
name: Optional[str],
|
496
617
|
cloud_id: Optional[str],
|
497
618
|
enable_log_ingestion: Optional[bool],
|
498
619
|
enable_system_cluster: Optional[bool],
|
499
620
|
spec_file: Optional[str],
|
621
|
+
resource: Optional[str],
|
622
|
+
cloud_resource_id: Optional[str],
|
500
623
|
) -> None:
|
501
|
-
if cloud_name and name and cloud_name != name:
|
502
|
-
raise click.ClickException(
|
503
|
-
"The positional argument CLOUD_NAME and the keyword argument --name "
|
504
|
-
"were both provided. Please only provide one of these two arguments."
|
505
|
-
)
|
506
|
-
|
507
624
|
passed_enable_disable_flags = any(
|
508
625
|
[enable_log_ingestion is not None, enable_system_cluster is not None]
|
509
626
|
)
|
510
|
-
if passed_enable_disable_flags and spec_file:
|
511
|
-
raise click.ClickException(
|
512
|
-
"Invalid combination of arguments: --spec-file should not be provided with any other enable/disable flags."
|
513
|
-
)
|
514
627
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
"cloud provider. If you are sure you want to enable this feature, "
|
524
|
-
'please type "consent"',
|
525
|
-
type=str,
|
526
|
-
)
|
527
|
-
if consent_message != "consent":
|
528
|
-
raise click.ClickException(
|
529
|
-
'You must type "consent" to enable log ingestion.'
|
530
|
-
)
|
531
|
-
elif enable_log_ingestion is False:
|
532
|
-
confirm_response = click.confirm(
|
533
|
-
"--disable-log-ingestion is specified. Please note the logs that's "
|
534
|
-
"already ingested will not be deleted. Existing clusters will not stop"
|
535
|
-
"the log ingestion until you restart them. Logs are automatically "
|
536
|
-
"deleted after 30 days from the time of ingestion. Are you sure you "
|
537
|
-
"want to disable log ingestion?"
|
538
|
-
)
|
539
|
-
if not confirm_response:
|
540
|
-
raise click.ClickException("You must confirm to disable log ingestion.")
|
628
|
+
_validate_cloud_config_update_args(
|
629
|
+
cloud_name,
|
630
|
+
name,
|
631
|
+
resource,
|
632
|
+
cloud_resource_id,
|
633
|
+
passed_enable_disable_flags,
|
634
|
+
spec_file,
|
635
|
+
)
|
541
636
|
|
637
|
+
cloud_name_resolved = cloud_name or name
|
638
|
+
|
639
|
+
if passed_enable_disable_flags:
|
640
|
+
_handle_log_ingestion_config(enable_log_ingestion)
|
542
641
|
CloudController().update_cloud_config(
|
543
|
-
cloud_name=
|
642
|
+
cloud_name=cloud_name_resolved,
|
544
643
|
cloud_id=cloud_id,
|
545
644
|
enable_log_ingestion=enable_log_ingestion,
|
546
645
|
)
|
547
646
|
|
548
|
-
|
549
|
-
if enable_system_cluster is True:
|
550
|
-
confirm_response = click.confirm(
|
551
|
-
"--enable-system-cluster is specified. Please note that this will enable "
|
552
|
-
"system cluster functionality for the cloud and will incur extra cost. "
|
553
|
-
"Are you sure you want to enable system cluster?"
|
554
|
-
)
|
555
|
-
elif enable_system_cluster is False:
|
556
|
-
confirm_response = click.confirm(
|
557
|
-
"--disable-system-cluster is specified. This will disable system cluster "
|
558
|
-
"functionality for the cloud. Please note that this will not terminate "
|
559
|
-
"the system cluster if it is currently running. "
|
560
|
-
"Are you sure you want to disable system cluster?"
|
561
|
-
)
|
562
|
-
if enable_system_cluster is not None and not confirm_response:
|
563
|
-
raise click.ClickException(
|
564
|
-
f"You must confirm to {'enable' if enable_system_cluster else 'disable'} system cluster."
|
565
|
-
)
|
566
|
-
|
647
|
+
_handle_system_cluster_config(enable_system_cluster)
|
567
648
|
CloudController().update_system_cluster_config(
|
568
|
-
cloud_name=
|
649
|
+
cloud_name=cloud_name_resolved,
|
569
650
|
cloud_id=cloud_id,
|
570
651
|
system_cluster_enabled=enable_system_cluster,
|
571
652
|
)
|
572
653
|
elif spec_file:
|
573
654
|
CloudController().update_cloud_config(
|
574
|
-
cloud_name=
|
655
|
+
cloud_name=cloud_name_resolved,
|
656
|
+
cloud_id=cloud_id,
|
657
|
+
spec_file=spec_file,
|
658
|
+
resource=resource,
|
659
|
+
cloud_resource_id=cloud_resource_id,
|
575
660
|
)
|
576
661
|
else:
|
577
662
|
raise click.ClickException(
|