anyscale 0.26.49__py3-none-any.whl → 0.26.51__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/client/README.md CHANGED
@@ -210,6 +210,7 @@ Class | Method | HTTP request | Description
210
210
  *DefaultApi* | [**get_job_queue_api_v2_job_queues_job_queue_id_get**](docs/DefaultApi.md#get_job_queue_api_v2_job_queues_job_queue_id_get) | **GET** /api/v2/job_queues/{job_queue_id} | Get Job Queue
211
211
  *DefaultApi* | [**get_jobs_api_v2_dataset_runs_jobs_get**](docs/DefaultApi.md#get_jobs_api_v2_dataset_runs_jobs_get) | **GET** /api/v2/dataset_runs/jobs | Get Jobs
212
212
  *DefaultApi* | [**get_lb_resource_api_v2_clouds_with_cloud_resource_gcp_router_cloud_id_get_lb_resource_post**](docs/DefaultApi.md#get_lb_resource_api_v2_clouds_with_cloud_resource_gcp_router_cloud_id_get_lb_resource_post) | **POST** /api/v2/clouds_with_cloud_resource_gcp_router/{cloud_id}/get_lb_resource | Get Lb Resource
213
+ *DefaultApi* | [**get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post**](docs/DefaultApi.md#get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post) | **POST** /api/v2/clouds_with_cloud_resource_router/{cloud_id}/get_lb_resource | Get Lb Resource
213
214
  *DefaultApi* | [**get_log_files_api_v2_logs_get_log_files_post**](docs/DefaultApi.md#get_log_files_api_v2_logs_get_log_files_post) | **POST** /api/v2/logs/get_log_files | Get Log Files
214
215
  *DefaultApi* | [**get_manage_billing_url_api_v2_organization_billing_manage_billing_url_get**](docs/DefaultApi.md#get_manage_billing_url_api_v2_organization_billing_manage_billing_url_get) | **GET** /api/v2/organization_billing/manage_billing_url | Get Manage Billing Url
215
216
  *DefaultApi* | [**get_metronome_customer_info_api_v2_metronome_customer_info_organization_id_get**](docs/DefaultApi.md#get_metronome_customer_info_api_v2_metronome_customer_info_organization_id_get) | **GET** /api/v2/metronome_customer_info/{organization_id} | Get Metronome Customer Info
@@ -308,6 +309,7 @@ Class | Method | HTTP request | Description
308
309
  *DefaultApi* | [**put_workspace_proxied_dataplane_artifacts_api_v2_experimental_workspaces_workspace_id_proxied_dataplane_artifacts_put**](docs/DefaultApi.md#put_workspace_proxied_dataplane_artifacts_api_v2_experimental_workspaces_workspace_id_proxied_dataplane_artifacts_put) | **PUT** /api/v2/experimental_workspaces/{workspace_id}/proxied_dataplane_artifacts | Put Workspace Proxied Dataplane Artifacts
309
310
  *DefaultApi* | [**put_workspace_wandb_run_details_api_v2_integrations_workspace_wandb_run_details_workspace_id_put**](docs/DefaultApi.md#put_workspace_wandb_run_details_api_v2_integrations_workspace_wandb_run_details_workspace_id_put) | **PUT** /api/v2/integrations/workspace_wandb_run_details/{workspace_id} | Put Workspace Wandb Run Details
310
311
  *DefaultApi* | [**query_aggregated_logs_api_v2_logs_query_aggregated_logs_get**](docs/DefaultApi.md#query_aggregated_logs_api_v2_logs_query_aggregated_logs_get) | **GET** /api/v2/logs/query_aggregated_logs | Query Aggregated Logs
312
+ *DefaultApi* | [**query_api_v2_logs_query_get**](docs/DefaultApi.md#query_api_v2_logs_query_get) | **GET** /api/v2/logs/query | Query
311
313
  *DefaultApi* | [**query_api_v2_metrics_query_get**](docs/DefaultApi.md#query_api_v2_metrics_query_get) | **GET** /api/v2/metrics/query | Query
312
314
  *DefaultApi* | [**query_range_api_v2_metrics_query_range_get**](docs/DefaultApi.md#query_range_api_v2_metrics_query_range_get) | **GET** /api/v2/metrics/query_range | Query Range
313
315
  *DefaultApi* | [**receive_cli_usage_api_v2_cli_usage_post**](docs/DefaultApi.md#receive_cli_usage_api_v2_cli_usage_post) | **POST** /api/v2/cli_usage/ | Receive Cli Usage
@@ -16013,6 +16013,120 @@ class DefaultApi(object):
16013
16013
  _request_timeout=local_var_params.get('_request_timeout'),
16014
16014
  collection_formats=collection_formats)
16015
16015
 
16016
+ def get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post(self, cloud_id, **kwargs): # noqa: E501
16017
+ """Get Lb Resource # noqa: E501
16018
+
16019
+ Get lb resources for the cloud. # noqa: E501
16020
+ This method makes a synchronous HTTP request by default. To make an
16021
+ asynchronous HTTP request, please pass async_req=True
16022
+ >>> thread = api.get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post(cloud_id, async_req=True)
16023
+ >>> result = thread.get()
16024
+
16025
+ :param async_req bool: execute request asynchronously
16026
+ :param str cloud_id: (required)
16027
+ :param _preload_content: if False, the urllib3.HTTPResponse object will
16028
+ be returned without reading/decoding response
16029
+ data. Default is True.
16030
+ :param _request_timeout: timeout setting for this request. If one
16031
+ number provided, it will be total request
16032
+ timeout. It can also be a pair (tuple) of
16033
+ (connection, read) timeouts.
16034
+ :return: LbresourceResponse
16035
+ If the method is called asynchronously,
16036
+ returns the request thread.
16037
+ """
16038
+ kwargs['_return_http_data_only'] = True
16039
+ return self.get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post_with_http_info(cloud_id, **kwargs) # noqa: E501
16040
+
16041
+ def get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post_with_http_info(self, cloud_id, **kwargs): # noqa: E501
16042
+ """Get Lb Resource # noqa: E501
16043
+
16044
+ Get lb resources for the cloud. # noqa: E501
16045
+ This method makes a synchronous HTTP request by default. To make an
16046
+ asynchronous HTTP request, please pass async_req=True
16047
+ >>> thread = api.get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post_with_http_info(cloud_id, async_req=True)
16048
+ >>> result = thread.get()
16049
+
16050
+ :param async_req bool: execute request asynchronously
16051
+ :param str cloud_id: (required)
16052
+ :param _return_http_data_only: response data without head status code
16053
+ and headers
16054
+ :param _preload_content: if False, the urllib3.HTTPResponse object will
16055
+ be returned without reading/decoding response
16056
+ data. Default is True.
16057
+ :param _request_timeout: timeout setting for this request. If one
16058
+ number provided, it will be total request
16059
+ timeout. It can also be a pair (tuple) of
16060
+ (connection, read) timeouts.
16061
+ :return: tuple(LbresourceResponse, status_code(int), headers(HTTPHeaderDict))
16062
+ If the method is called asynchronously,
16063
+ returns the request thread.
16064
+ """
16065
+
16066
+ local_var_params = locals()
16067
+
16068
+ all_params = [
16069
+ 'cloud_id'
16070
+ ]
16071
+ all_params.extend(
16072
+ [
16073
+ 'async_req',
16074
+ '_return_http_data_only',
16075
+ '_preload_content',
16076
+ '_request_timeout'
16077
+ ]
16078
+ )
16079
+
16080
+ for key, val in six.iteritems(local_var_params['kwargs']):
16081
+ if key not in all_params:
16082
+ raise ApiTypeError(
16083
+ "Got an unexpected keyword argument '%s'"
16084
+ " to method get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post" % key
16085
+ )
16086
+ local_var_params[key] = val
16087
+ del local_var_params['kwargs']
16088
+ # verify the required parameter 'cloud_id' is set
16089
+ if self.api_client.client_side_validation and ('cloud_id' not in local_var_params or # noqa: E501
16090
+ local_var_params['cloud_id'] is None): # noqa: E501
16091
+ raise ApiValueError("Missing the required parameter `cloud_id` when calling `get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post`") # noqa: E501
16092
+
16093
+ collection_formats = {}
16094
+
16095
+ path_params = {}
16096
+ if 'cloud_id' in local_var_params:
16097
+ path_params['cloud_id'] = local_var_params['cloud_id'] # noqa: E501
16098
+
16099
+ query_params = []
16100
+
16101
+ header_params = {}
16102
+
16103
+ form_params = []
16104
+ local_var_files = {}
16105
+
16106
+ body_params = None
16107
+ # HTTP header `Accept`
16108
+ header_params['Accept'] = self.api_client.select_header_accept(
16109
+ ['application/json']) # noqa: E501
16110
+
16111
+ # Authentication setting
16112
+ auth_settings = [] # noqa: E501
16113
+
16114
+ return self.api_client.call_api(
16115
+ '/api/v2/clouds_with_cloud_resource_router/{cloud_id}/get_lb_resource', 'POST',
16116
+ path_params,
16117
+ query_params,
16118
+ header_params,
16119
+ body=body_params,
16120
+ post_params=form_params,
16121
+ files=local_var_files,
16122
+ response_type='LbresourceResponse', # noqa: E501
16123
+ auth_settings=auth_settings,
16124
+ async_req=local_var_params.get('async_req'),
16125
+ _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501
16126
+ _preload_content=local_var_params.get('_preload_content', True),
16127
+ _request_timeout=local_var_params.get('_request_timeout'),
16128
+ collection_formats=collection_formats)
16129
+
16016
16130
  def get_log_files_api_v2_logs_get_log_files_post(self, **kwargs): # noqa: E501
16017
16131
  """Get Log Files # noqa: E501
16018
16132
 
@@ -28219,6 +28333,181 @@ class DefaultApi(object):
28219
28333
  _request_timeout=local_var_params.get('_request_timeout'),
28220
28334
  collection_formats=collection_formats)
28221
28335
 
28336
+ def query_api_v2_logs_query_get(self, logql_query, start, end, source_type, **kwargs): # noqa: E501
28337
+ """Query # noqa: E501
28338
+
28339
+ Fetching logs using LogQL queries. # noqa: E501
28340
+ This method makes a synchronous HTTP request by default. To make an
28341
+ asynchronous HTTP request, please pass async_req=True
28342
+ >>> thread = api.query_api_v2_logs_query_get(logql_query, start, end, source_type, async_req=True)
28343
+ >>> result = thread.get()
28344
+
28345
+ :param async_req bool: execute request asynchronously
28346
+ :param str logql_query: LogQL query string to execute against the logs. This should be a valid Loki LogQL expression. (required)
28347
+ :param float start: The start time for the query as a nanosecond Unix epoch. (required)
28348
+ :param float end: The end time for the query as a nanosecond Unix epoch. (required)
28349
+ :param str source_type: The type of logs to query. Must be one of \"application\" or \"system\". (required)
28350
+ :param str cluster_id: The cluster id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28351
+ :param str workspace_id: The workspace id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28352
+ :param str ha_job_id: The production job id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28353
+ :param str service_id: The service id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28354
+ :param int page_size: Number of chunks to fetch. Defaults to 400. Max of 1000.
28355
+ :param bool reverse_sort: Whether the result should be sorted by descending timestamp. Also determines the query direction. When false, it will start to query from the start and return results until it reaches the page_size or the end. When true, it will start to query from the end and return results until it reaches the page_size or the start. Default to false.
28356
+ :param _preload_content: if False, the urllib3.HTTPResponse object will
28357
+ be returned without reading/decoding response
28358
+ data. Default is True.
28359
+ :param _request_timeout: timeout setting for this request. If one
28360
+ number provided, it will be total request
28361
+ timeout. It can also be a pair (tuple) of
28362
+ (connection, read) timeouts.
28363
+ :return: LogitembatchResponse
28364
+ If the method is called asynchronously,
28365
+ returns the request thread.
28366
+ """
28367
+ kwargs['_return_http_data_only'] = True
28368
+ return self.query_api_v2_logs_query_get_with_http_info(logql_query, start, end, source_type, **kwargs) # noqa: E501
28369
+
28370
+ def query_api_v2_logs_query_get_with_http_info(self, logql_query, start, end, source_type, **kwargs): # noqa: E501
28371
+ """Query # noqa: E501
28372
+
28373
+ Fetching logs using LogQL queries. # noqa: E501
28374
+ This method makes a synchronous HTTP request by default. To make an
28375
+ asynchronous HTTP request, please pass async_req=True
28376
+ >>> thread = api.query_api_v2_logs_query_get_with_http_info(logql_query, start, end, source_type, async_req=True)
28377
+ >>> result = thread.get()
28378
+
28379
+ :param async_req bool: execute request asynchronously
28380
+ :param str logql_query: LogQL query string to execute against the logs. This should be a valid Loki LogQL expression. (required)
28381
+ :param float start: The start time for the query as a nanosecond Unix epoch. (required)
28382
+ :param float end: The end time for the query as a nanosecond Unix epoch. (required)
28383
+ :param str source_type: The type of logs to query. Must be one of \"application\" or \"system\". (required)
28384
+ :param str cluster_id: The cluster id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28385
+ :param str workspace_id: The workspace id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28386
+ :param str ha_job_id: The production job id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28387
+ :param str service_id: The service id used to fetch logs. Exactly one of cluster_id, workspace_id, ha_job_id, or service_id must be set.
28388
+ :param int page_size: Number of chunks to fetch. Defaults to 400. Max of 1000.
28389
+ :param bool reverse_sort: Whether the result should be sorted by descending timestamp. Also determines the query direction. When false, it will start to query from the start and return results until it reaches the page_size or the end. When true, it will start to query from the end and return results until it reaches the page_size or the start. Default to false.
28390
+ :param _return_http_data_only: response data without head status code
28391
+ and headers
28392
+ :param _preload_content: if False, the urllib3.HTTPResponse object will
28393
+ be returned without reading/decoding response
28394
+ data. Default is True.
28395
+ :param _request_timeout: timeout setting for this request. If one
28396
+ number provided, it will be total request
28397
+ timeout. It can also be a pair (tuple) of
28398
+ (connection, read) timeouts.
28399
+ :return: tuple(LogitembatchResponse, status_code(int), headers(HTTPHeaderDict))
28400
+ If the method is called asynchronously,
28401
+ returns the request thread.
28402
+ """
28403
+
28404
+ local_var_params = locals()
28405
+
28406
+ all_params = [
28407
+ 'logql_query',
28408
+ 'start',
28409
+ 'end',
28410
+ 'source_type',
28411
+ 'cluster_id',
28412
+ 'workspace_id',
28413
+ 'ha_job_id',
28414
+ 'service_id',
28415
+ 'page_size',
28416
+ 'reverse_sort'
28417
+ ]
28418
+ all_params.extend(
28419
+ [
28420
+ 'async_req',
28421
+ '_return_http_data_only',
28422
+ '_preload_content',
28423
+ '_request_timeout'
28424
+ ]
28425
+ )
28426
+
28427
+ for key, val in six.iteritems(local_var_params['kwargs']):
28428
+ if key not in all_params:
28429
+ raise ApiTypeError(
28430
+ "Got an unexpected keyword argument '%s'"
28431
+ " to method query_api_v2_logs_query_get" % key
28432
+ )
28433
+ local_var_params[key] = val
28434
+ del local_var_params['kwargs']
28435
+ # verify the required parameter 'logql_query' is set
28436
+ if self.api_client.client_side_validation and ('logql_query' not in local_var_params or # noqa: E501
28437
+ local_var_params['logql_query'] is None): # noqa: E501
28438
+ raise ApiValueError("Missing the required parameter `logql_query` when calling `query_api_v2_logs_query_get`") # noqa: E501
28439
+ # verify the required parameter 'start' is set
28440
+ if self.api_client.client_side_validation and ('start' not in local_var_params or # noqa: E501
28441
+ local_var_params['start'] is None): # noqa: E501
28442
+ raise ApiValueError("Missing the required parameter `start` when calling `query_api_v2_logs_query_get`") # noqa: E501
28443
+ # verify the required parameter 'end' is set
28444
+ if self.api_client.client_side_validation and ('end' not in local_var_params or # noqa: E501
28445
+ local_var_params['end'] is None): # noqa: E501
28446
+ raise ApiValueError("Missing the required parameter `end` when calling `query_api_v2_logs_query_get`") # noqa: E501
28447
+ # verify the required parameter 'source_type' is set
28448
+ if self.api_client.client_side_validation and ('source_type' not in local_var_params or # noqa: E501
28449
+ local_var_params['source_type'] is None): # noqa: E501
28450
+ raise ApiValueError("Missing the required parameter `source_type` when calling `query_api_v2_logs_query_get`") # noqa: E501
28451
+
28452
+ if self.api_client.client_side_validation and 'source_type' in local_var_params and not re.search(r'^(application|system)$', local_var_params['source_type']): # noqa: E501
28453
+ raise ApiValueError("Invalid value for parameter `source_type` when calling `query_api_v2_logs_query_get`, must conform to the pattern `/^(application|system)$/`") # noqa: E501
28454
+ if self.api_client.client_side_validation and 'page_size' in local_var_params and local_var_params['page_size'] > 1000: # noqa: E501
28455
+ raise ApiValueError("Invalid value for parameter `page_size` when calling `query_api_v2_logs_query_get`, must be a value less than or equal to `1000`") # noqa: E501
28456
+ collection_formats = {}
28457
+
28458
+ path_params = {}
28459
+
28460
+ query_params = []
28461
+ if 'logql_query' in local_var_params and local_var_params['logql_query'] is not None: # noqa: E501
28462
+ query_params.append(('logql_query', local_var_params['logql_query'])) # noqa: E501
28463
+ if 'start' in local_var_params and local_var_params['start'] is not None: # noqa: E501
28464
+ query_params.append(('start', local_var_params['start'])) # noqa: E501
28465
+ if 'end' in local_var_params and local_var_params['end'] is not None: # noqa: E501
28466
+ query_params.append(('end', local_var_params['end'])) # noqa: E501
28467
+ if 'source_type' in local_var_params and local_var_params['source_type'] is not None: # noqa: E501
28468
+ query_params.append(('source_type', local_var_params['source_type'])) # noqa: E501
28469
+ if 'cluster_id' in local_var_params and local_var_params['cluster_id'] is not None: # noqa: E501
28470
+ query_params.append(('cluster_id', local_var_params['cluster_id'])) # noqa: E501
28471
+ if 'workspace_id' in local_var_params and local_var_params['workspace_id'] is not None: # noqa: E501
28472
+ query_params.append(('workspace_id', local_var_params['workspace_id'])) # noqa: E501
28473
+ if 'ha_job_id' in local_var_params and local_var_params['ha_job_id'] is not None: # noqa: E501
28474
+ query_params.append(('ha_job_id', local_var_params['ha_job_id'])) # noqa: E501
28475
+ if 'service_id' in local_var_params and local_var_params['service_id'] is not None: # noqa: E501
28476
+ query_params.append(('service_id', local_var_params['service_id'])) # noqa: E501
28477
+ if 'page_size' in local_var_params and local_var_params['page_size'] is not None: # noqa: E501
28478
+ query_params.append(('page_size', local_var_params['page_size'])) # noqa: E501
28479
+ if 'reverse_sort' in local_var_params and local_var_params['reverse_sort'] is not None: # noqa: E501
28480
+ query_params.append(('reverse_sort', local_var_params['reverse_sort'])) # noqa: E501
28481
+
28482
+ header_params = {}
28483
+
28484
+ form_params = []
28485
+ local_var_files = {}
28486
+
28487
+ body_params = None
28488
+ # HTTP header `Accept`
28489
+ header_params['Accept'] = self.api_client.select_header_accept(
28490
+ ['application/json']) # noqa: E501
28491
+
28492
+ # Authentication setting
28493
+ auth_settings = [] # noqa: E501
28494
+
28495
+ return self.api_client.call_api(
28496
+ '/api/v2/logs/query', 'GET',
28497
+ path_params,
28498
+ query_params,
28499
+ header_params,
28500
+ body=body_params,
28501
+ post_params=form_params,
28502
+ files=local_var_files,
28503
+ response_type='LogitembatchResponse', # noqa: E501
28504
+ auth_settings=auth_settings,
28505
+ async_req=local_var_params.get('async_req'),
28506
+ _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501
28507
+ _preload_content=local_var_params.get('_preload_content', True),
28508
+ _request_timeout=local_var_params.get('_request_timeout'),
28509
+ collection_formats=collection_formats)
28510
+
28222
28511
  def query_api_v2_metrics_query_get(self, promql_query, **kwargs): # noqa: E501
28223
28512
  """Query # noqa: E501
28224
28513
 
@@ -34,7 +34,7 @@ log = BlockLogger() # CLI Logger
34
34
 
35
35
  # Constants for SSH configuration
36
36
  HTTPS_PORT = "443"
37
- SSH_TIMEOUT_SECONDS = 45
37
+ SSH_TEST_TIMEOUT_SECONDS = 8
38
38
  WSS_PATH = "/sshws"
39
39
  PREFERRED_AUTH_METHOD = "PreferredAuthentications=publickey"
40
40
 
@@ -319,15 +319,10 @@ def _parse_user_args(user_args: List[str]) -> Tuple[List[str], List[str]]:
319
319
  return user_options, user_command
320
320
 
321
321
 
322
- def _try_https_connection(
323
- workspace_obj: Workspace,
324
- workspace_private_sdk,
325
- host_name: str,
326
- config_file: str,
327
- ctx_args: List[str],
328
- shell_command: str,
322
+ def _test_https_connectivity(
323
+ workspace_obj: Workspace, workspace_private_sdk, host_name: str, config_file: str,
329
324
  ) -> bool:
330
- """Attempt HTTPS SSH connection. Returns True if successful."""
325
+ """Test HTTPS SSH connectivity with a quick command. Returns True if available."""
331
326
  try:
332
327
  cluster = workspace_private_sdk.client.get_workspace_cluster(workspace_obj.id)
333
328
  if not cluster:
@@ -337,35 +332,62 @@ def _try_https_connection(
337
332
  workspace_obj, workspace_private_sdk, host_name, config_file
338
333
  )
339
334
 
340
- ssh_cmd = _build_ssh_command(ssh_config, ctx_args, shell_command)
335
+ # Build a test command using the same logic as the actual connection
336
+ # but with a simple echo command that exits immediately
337
+ test_args = [
338
+ "-o",
339
+ "ConnectTimeout=5",
340
+ "-o",
341
+ "BatchMode=yes",
342
+ "echo",
343
+ "connectivity_test",
344
+ ]
345
+ test_cmd = _build_ssh_command(ssh_config, test_args, "")
341
346
 
342
- # Try HTTPS connection with a timeout
347
+ # Run test with a timeout
343
348
  result = subprocess.run(
344
- ssh_cmd,
349
+ test_cmd,
345
350
  check=False,
346
- timeout=SSH_TIMEOUT_SECONDS,
347
- stderr=subprocess.DEVNULL,
351
+ timeout=SSH_TEST_TIMEOUT_SECONDS,
352
+ capture_output=True,
353
+ text=True,
348
354
  )
349
355
 
350
- return result.returncode == 0
356
+ # Check if we got the expected output
357
+ if result.returncode == 0 and "connectivity_test" in result.stdout:
358
+ return True
359
+
360
+ # Connection failed - no need to show error code to user
361
+ return False
351
362
 
352
363
  except subprocess.TimeoutExpired:
353
- print(
354
- "HTTPS connection timed out or failed (SSH proxy may not be available), "
355
- "falling back to Legacy SSH connection..."
356
- )
364
+ # Silent failure - the main code will show a user-friendly message
357
365
  return False
358
366
  except OSError:
359
- print(
360
- "HTTPS connection timed out or failed (SSH proxy may not be available), "
361
- "falling back to Legacy SSH connection..."
362
- )
367
+ # Silent failure
363
368
  return False
364
369
  except (click.ClickException, ValueError, AttributeError, KeyError, TypeError):
365
- print("HTTPS setup failed, falling back to Legacy SSH connection...")
370
+ # Silent failure
366
371
  return False
367
372
 
368
373
 
374
+ def _execute_https_ssh(
375
+ workspace_obj: Workspace,
376
+ workspace_private_sdk,
377
+ host_name: str,
378
+ config_file: str,
379
+ ctx_args: List[str],
380
+ shell_command: str,
381
+ ) -> None:
382
+ """Execute HTTPS SSH connection without timeout."""
383
+ ssh_config = _setup_https_connection(
384
+ workspace_obj, workspace_private_sdk, host_name, config_file
385
+ )
386
+ ssh_cmd = _build_ssh_command(ssh_config, ctx_args, shell_command)
387
+ # Run the actual SSH session without any timeout
388
+ subprocess.run(ssh_cmd, check=False)
389
+
390
+
369
391
  def _execute_legacy_ssh(
370
392
  ssh_target_host: str, config_file: str, ctx_args: List[str], shell_command: str,
371
393
  ) -> None:
@@ -857,21 +879,32 @@ id should be used, specifying both will result in an error.
857
879
  )
858
880
 
859
881
  if cluster:
860
- https_connection_successful = _try_https_connection(
882
+ https_connection_successful = _test_https_connectivity(
861
883
  workspace_obj,
862
884
  workspace_private_sdk,
863
885
  host_name,
864
886
  config_file,
865
- ctx.args,
866
- shell_command,
867
887
  )
868
888
 
869
889
  except (ValueError, AttributeError, KeyError, TypeError):
870
890
  # If we can't get workspace/cluster info, proceed with legacy SSH
871
891
  pass
872
892
 
873
- # Run legacy SSH command if HTTPS wasn't successful or --legacy was specified
874
- if not https_connection_successful:
893
+ # Execute the appropriate SSH connection based on test results
894
+ if https_connection_successful:
895
+ # HTTPS connectivity test passed, run actual SSH session without timeout
896
+ _execute_https_ssh(
897
+ workspace_obj,
898
+ workspace_private_sdk,
899
+ host_name,
900
+ config_file,
901
+ ctx.args,
902
+ shell_command,
903
+ )
904
+ else:
905
+ # HTTPS test failed or --legacy was specified, use legacy SSH
906
+ if not legacy: # Only show message if we tried HTTPS first
907
+ print("Connecting via standard SSH...")
875
908
  _execute_legacy_ssh(
876
909
  ssh_target_host, config_file, ctx.args, shell_command
877
910
  )
@@ -118,6 +118,7 @@ from anyscale.utils.cloud_utils import (
118
118
  modify_memorydb_parameter_group,
119
119
  validate_aws_credentials,
120
120
  verify_anyscale_access,
121
+ wait_for_aws_lb_resource_termination,
121
122
  wait_for_gcp_lb_resource_termination,
122
123
  )
123
124
  from anyscale.utils.imports.gcp import (
@@ -3525,6 +3526,15 @@ class CloudController(BaseController):
3525
3526
  # Clean up cloud resources
3526
3527
  try:
3527
3528
  if cloud_provider == CloudProviders.AWS:
3529
+ if not (cloud.is_aioa or cloud.compute_stack == ComputeStack.K8S):
3530
+ # Delete services resources
3531
+ self.delete_aws_lb_cfn_stack(cloud=cloud)
3532
+ with self.log.spinner("Deleting load balancing resources..."):
3533
+ wait_for_aws_lb_resource_termination(
3534
+ api_client=self.api_client, cloud_id=cloud_id
3535
+ )
3536
+ self.delete_aws_tls_certificates(cloud=cloud)
3537
+
3528
3538
  self.delete_all_aws_resources(cloud)
3529
3539
  elif cloud_provider == CloudProviders.GCP:
3530
3540
  with self.log.spinner("Deleting load balancing resources..."):
@@ -3585,10 +3595,6 @@ class CloudController(BaseController):
3585
3595
  # No resources to delete for hosted and k8s clouds
3586
3596
  return True
3587
3597
 
3588
- # Delete services resources
3589
- self.delete_aws_lb_cfn_stack(cloud=cloud)
3590
- self.delete_aws_tls_certificates(cloud=cloud)
3591
-
3592
3598
  # Clean up cloud resources
3593
3599
  if cloud.is_bring_your_own_resource is False: # managed cloud
3594
3600
  # Delete AWS cloud resources by deleting the cfn stack
@@ -3601,7 +3607,6 @@ class CloudController(BaseController):
3601
3607
  return True
3602
3608
 
3603
3609
  def delete_aws_lb_cfn_stack(self, cloud: CloudWithCloudResource) -> bool:
3604
-
3605
3610
  tag_name = "anyscale-cloud-id"
3606
3611
  key_name = cloud.id
3607
3612
 
@@ -137,6 +137,26 @@ def wait_for_gcp_lb_resource_termination(
137
137
  )
138
138
 
139
139
 
140
+ def wait_for_aws_lb_resource_termination(
141
+ api_client: DefaultApi,
142
+ cloud_id: str,
143
+ timeout_s: int = 900, # 15 minute timeout
144
+ poll_interval_s: int = 10, # Poll every 10 seconds
145
+ ):
146
+ start = time.time()
147
+ while time.time() - start < timeout_s:
148
+ response = api_client.get_lb_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get_lb_resource_post(
149
+ cloud_id=cloud_id
150
+ ).result
151
+ if response.is_terminated:
152
+ break
153
+ time.sleep(poll_interval_s)
154
+ else:
155
+ raise ClickException(
156
+ f"LB resources and namespace termination timed out after {timeout_s} seconds."
157
+ )
158
+
159
+
140
160
  class CloudSetupError(str, Enum):
141
161
  ANYSCALE_ACCESS_DENIED = "ANYSCALE_ACCESS_DENIED"
142
162
  RESOURCE_NOT_FOUND = "RESOURCE_NOT_FOUND"
anyscale/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.26.49"
1
+ __version__ = "0.26.51"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anyscale
3
- Version: 0.26.49
3
+ Version: 0.26.51
4
4
  Summary: Command Line Interface for Anyscale
5
5
  Author: Anyscale Inc.
6
6
  License: AS License
@@ -28,7 +28,7 @@ anyscale/snapshot.py,sha256=UGJT5C1s_4xmQxjWODK5DFpGxHRBX5jOCdSCqXESH8E,1685
28
28
  anyscale/tables.py,sha256=TV4F2uLnwehvbkAfaP7iuLlT2wLIo6ORH2LVdRGXW5g,2840
29
29
  anyscale/telemetry.py,sha256=U90C2Vgx48z9PMTI6EbzHFbP3jWnDUutbIfMPBb8-SI,14711
30
30
  anyscale/util.py,sha256=0iSmKKsDFV0i2eRmVQ1W60Sgh2g-vPeBoBw3ra3m6eI,42782
31
- anyscale/version.py,sha256=vFxJ_KKIQ2jL69pJLX3oYkt-Bt_G2kmqY-WBfibLQa8,24
31
+ anyscale/version.py,sha256=NqLTzru5GGXVWj7EBlduJ32JLhuH-lqYkV-B3wOrAH0,24
32
32
  anyscale/workspace_utils.py,sha256=OViE88CnIF5ruVxd3kazQ0Mf2BxqtMq6wx-XQ5A2cp8,1204
33
33
  anyscale/_private/anyscale_client/README.md,sha256=zKSxkDTTNjrty018PaCsV22LNYDk9AZ7j0JKxOLAxvE,3732
34
34
  anyscale/_private/anyscale_client/__init__.py,sha256=807Blx3RHQeS8BmKZcsOQQ4dYoKlCnpm6Bdsif2CrHg,337
@@ -106,7 +106,7 @@ anyscale/background/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
106
106
  anyscale/background/job_runner.py,sha256=LTuv9JOahyv6C9i7DLQAONgQF6--FfYZEmJrKy-sUG8,2687
107
107
  anyscale/client/.gitignore,sha256=JZyvYEtT2DCSK9V5Joi6lQofhMik4PXiJRCWsg7SvqI,807
108
108
  anyscale/client/.openapi-generator-ignore,sha256=pu2PTide7pJtJ-DFLzDy0cTYQJRlrB-8RRH3zGLeUds,1040
109
- anyscale/client/README.md,sha256=st5IPaeuNGo81hxvz3o6bvjESLHlmrG0jayEy5gwbsc,115609
109
+ anyscale/client/README.md,sha256=2mNo7LqoRCNdI7onaHVN4PHGW6xG6e7y2YpxMMV4NSE,116056
110
110
  anyscale/client/git_push.sh,sha256=EDCZOTTiLxbtPHmiU63qC99rGH67B7dhdPZdNUKivF0,1827
111
111
  anyscale/client/requirements.txt,sha256=dkVKYUStC5h_g_87SH7pRdhXCj7ySozAJMGAFEzGgFc,126
112
112
  anyscale/client/setup.cfg,sha256=l7bdKSIedeBhhoDtupsBwx1xPrlBf2yYeTH7a8kMga4,28
@@ -120,7 +120,7 @@ anyscale/client/openapi_client/configuration.py,sha256=Dd5XrlHwv-wxnf0C35PG_-HBQ
120
120
  anyscale/client/openapi_client/exceptions.py,sha256=3egwsXQG2j_vARbqgBxUO1xSltAhpfiHTYVP7VXTvU0,3792
121
121
  anyscale/client/openapi_client/rest.py,sha256=Ehj37v7GHW6SXV067Hze5HE42ayKaGi6a6ZlkR7u3Lg,12501
122
122
  anyscale/client/openapi_client/api/__init__.py,sha256=i8u7BI2xX1GrXTL3hN0pKpYIlnT-D_uDxH2ElOfYG1I,141
123
- anyscale/client/openapi_client/api/default_api.py,sha256=m2om4Ebc8EtVZJjZDO4BODx36JW042Ez1eevH-YoZi8,1864065
123
+ anyscale/client/openapi_client/api/default_api.py,sha256=EGL7wCSGy8bh17Knxpzruk-TkRUCpQrsfqL6Clkdd_0,1881652
124
124
  anyscale/client/openapi_client/models/__init__.py,sha256=vPm7p-GuqxDksMCS-9oaTub5QDrx9-Wg16MYzOeTyiU,51580
125
125
  anyscale/client/openapi_client/models/access_config.py,sha256=b2mA0qtuTA5PFbp6C61Jc_T2zUMaojM1v32IhZo0MfY,3648
126
126
  anyscale/client/openapi_client/models/actor_status.py,sha256=6xyX_aIqURj2raBdY9DmBxsdDACFrqqYvElGiM6YG2E,2813
@@ -781,7 +781,7 @@ anyscale/commands/session_commands_hidden.py,sha256=APEypnUB1yV2Rr6wdSFWy1vQbAnn
781
781
  anyscale/commands/user_commands.py,sha256=C-i1dGpdhboywN_2XgPS2BekKx2y6LZq8c8gvS0S-tY,1259
782
782
  anyscale/commands/util.py,sha256=N8gkVv9LBr5QypBGm2e_Pw2F2e_tiiR4YNLmn8CtsK0,5124
783
783
  anyscale/commands/workspace_commands.py,sha256=RjK8rPlIPoReZBb7RPB6z9aFp7gSmnsxDge8d3uj9t8,15768
784
- anyscale/commands/workspace_commands_v2.py,sha256=D6YmcjD7Db7KK6adaGxiyiIdlCzMa4Y1v_xVT_cWmmI,43582
784
+ anyscale/commands/workspace_commands_v2.py,sha256=vu8r2bNIFq88b594rGU82yW4o2rd_uCJnRO4lbSSHbI,44789
785
785
  anyscale/commands/anyscale_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
786
786
  anyscale/commands/anyscale_api/api_commands.py,sha256=Dze2wuzeZurlbxOu4YHZqln026yXgtWi_jxccyKANmw,473
787
787
  anyscale/commands/anyscale_api/session_operations_commands.py,sha256=LiavgWn2-F7b3GZD0ng_Q1HiEP4o32e8nO9yU92AgxI,803
@@ -797,7 +797,7 @@ anyscale/connect_utils/start_interactive_session.py,sha256=DbuIK2wuWofmbwJ9MLbsb
797
797
  anyscale/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
798
798
  anyscale/controllers/auth_controller.py,sha256=hDY2sPvUP8pvh8PnlDYH5rCHjQes2v3b_KBVjMbrzeE,5127
799
799
  anyscale/controllers/base_controller.py,sha256=1QFJoScFUV7YTzpKarhwPOc1SvI-xqX3TZmwxKonW6I,1998
800
- anyscale/controllers/cloud_controller.py,sha256=PWJzECBxeVnjDuP5G9ak5n06wjBiVrhzxeIjPS-M5w8,201250
800
+ anyscale/controllers/cloud_controller.py,sha256=f7QX0YX_F_FJGy6ggN1ougFtKDK4CPX0eAgaGfd2Uuk,201655
801
801
  anyscale/controllers/cloud_file_storage_utils.py,sha256=ifaqClEybTgxhqGWHYoH1vrlbxwjRuO-De_3666R2O4,6987
802
802
  anyscale/controllers/cloud_functional_verification_controller.py,sha256=YsEfdHT9hPtxy_3a5Q62UlRXW0iFJ1lVS4IZ_NHoemE,33399
803
803
  anyscale/controllers/cluster_controller.py,sha256=Sb5wVjrjpycg5iqmENAVtZ4iy9Kr6kM97_ck-KH85LM,28745
@@ -1058,7 +1058,7 @@ anyscale/user/_private/user_sdk.py,sha256=scw1PN5VXBgjS6sgrFBGEIjc1LSV6Dy6v8Irzd
1058
1058
  anyscale/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1059
1059
  anyscale/utils/cli_version_check_util.py,sha256=U2KU-NRf09pcs-ZZYUm1GQxs7Btp6N4Fv6CQeNoEeTM,2223
1060
1060
  anyscale/utils/cloud_update_utils.py,sha256=c53AQyg4OJBkNqTD-8hHvEpdTwtins1rTycifBbQbWI,34106
1061
- anyscale/utils/cloud_utils.py,sha256=ww4to0gL7mq1ALuJfpJ6GZvE4Vxn2qTkH834YO7ARoQ,11569
1061
+ anyscale/utils/cloud_utils.py,sha256=DtUkaIvKeX64Scia62fjnK61_gNMJr_H2e73C-ywF7k,12228
1062
1062
  anyscale/utils/cluster_debug.py,sha256=P_-20L4Rt4LVAIGX-y9F61z5XYO5QbNtqf2MYJxuy_g,6391
1063
1063
  anyscale/utils/connect_helpers.py,sha256=hlTKnaL27pABWPoW5nA5dpJW2ZG_2k7dXjnqtdzoBjo,5956
1064
1064
  anyscale/utils/deprecation_util.py,sha256=2i1SNQIziOZXO24IuBZZUEi4ild1bqk0gfZWl2KgpXw,1160
@@ -1091,10 +1091,10 @@ anyscale/workspace/__init__.py,sha256=Innbm5ZhCyADEVBiYSo_vbpKwUNcMzVSAfxIGKOYe6
1091
1091
  anyscale/workspace/commands.py,sha256=b1sqNseoPj-1VXznqQOLe0V_a663bOTvJX-TaOMJa1Y,14590
1092
1092
  anyscale/workspace/models.py,sha256=N2vHfoKzqvx1kVvbMVMcn0tKAiRab52rp0aQACS0RvQ,10044
1093
1093
  anyscale/workspace/_private/workspace_sdk.py,sha256=2CMeYfJt0UtIFCocDn1ukw1iI5esKHdopLe6duEs-qE,27599
1094
- anyscale-0.26.49.dist-info/licenses/LICENSE,sha256=UOPu974Wzsna6frFv1mu4VrZgNdZT7lbcNPzo5ue3qs,3494
1095
- anyscale-0.26.49.dist-info/licenses/NOTICE,sha256=gHqDhSnUYlRXX-mDOL5FtE7774oiKyV_HO80qM3r9Xo,196
1096
- anyscale-0.26.49.dist-info/METADATA,sha256=-DylcpFnALTEcq32zlMmahWkqBiA9OqWAiTisuUzawY,3231
1097
- anyscale-0.26.49.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1098
- anyscale-0.26.49.dist-info/entry_points.txt,sha256=NqO18sCZn6zG6J0S38itjcN00s7aE3C3v3k5lMAfCLk,51
1099
- anyscale-0.26.49.dist-info/top_level.txt,sha256=g3NVNS8Oh0NZwbFFgeX696C5MZZkS5dqV2NqcsbDRJE,9
1100
- anyscale-0.26.49.dist-info/RECORD,,
1094
+ anyscale-0.26.51.dist-info/licenses/LICENSE,sha256=UOPu974Wzsna6frFv1mu4VrZgNdZT7lbcNPzo5ue3qs,3494
1095
+ anyscale-0.26.51.dist-info/licenses/NOTICE,sha256=gHqDhSnUYlRXX-mDOL5FtE7774oiKyV_HO80qM3r9Xo,196
1096
+ anyscale-0.26.51.dist-info/METADATA,sha256=mANw_WHTludTuJwuxivjerG7TMJPhKUz8__CEhRKpWI,3231
1097
+ anyscale-0.26.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1098
+ anyscale-0.26.51.dist-info/entry_points.txt,sha256=NqO18sCZn6zG6J0S38itjcN00s7aE3C3v3k5lMAfCLk,51
1099
+ anyscale-0.26.51.dist-info/top_level.txt,sha256=g3NVNS8Oh0NZwbFFgeX696C5MZZkS5dqV2NqcsbDRJE,9
1100
+ anyscale-0.26.51.dist-info/RECORD,,