|
| 1 | +# Databricks CLI |
| 2 | +# Copyright 2017 Databricks, Inc. |
| 3 | +# |
| 4 | +# Licensed under the Apache License, Version 2.0 (the "License"), except |
| 5 | +# that the use of services to which certain application programming |
| 6 | +# interfaces (each, an "API") connect requires that the user first obtain |
| 7 | +# a license for the use of the APIs from Databricks, Inc. ("Databricks"), |
| 8 | +# by creating an account at www.databricks.com and agreeing to either (a) |
| 9 | +# the Community Edition Terms of Service, (b) the Databricks Terms of |
| 10 | +# Service, or (c) another written agreement between Licensee and Databricks |
| 11 | +# for the use of the APIs. |
| 12 | +# |
| 13 | +# You may not use this file except in compliance with the License. |
| 14 | +# You may obtain a copy of the License at |
| 15 | +# |
| 16 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 17 | +# |
| 18 | +# Unless required by applicable law or agreed to in writing, software |
| 19 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 20 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 21 | +# See the License for the specific language governing permissions and |
| 22 | +# limitations under the License. |
| 23 | + |
| 24 | +import click |
| 25 | +from tabulate import tabulate |
| 26 | + |
| 27 | +from databricks_cli.click_types import OutputClickType, JsonClickType, InstancePoolIdClickType |
| 28 | +from databricks_cli.instance_pools.api import InstancePoolsApi |
| 29 | +from databricks_cli.utils import eat_exceptions, CONTEXT_SETTINGS, pretty_format, json_cli_base, \ |
| 30 | + truncate_string |
| 31 | +from databricks_cli.configure.config import provide_api_client, profile_option, debug_option |
| 32 | +from databricks_cli.version import print_version_callback, version |
| 33 | + |
| 34 | + |
| 35 | +@click.command(context_settings=CONTEXT_SETTINGS) |
| 36 | +@click.option('--json-file', default=None, type=click.Path(), |
| 37 | + help='File containing JSON request to POST to /api/2.0/instance-pools/create.') |
| 38 | +@click.option('--json', default=None, type=JsonClickType(), |
| 39 | + help=JsonClickType.help('/api/2.0/instance-pools/create')) |
| 40 | +@debug_option |
| 41 | +@profile_option |
| 42 | +@eat_exceptions |
| 43 | +@provide_api_client |
| 44 | +def create_cli(api_client, json_file, json): |
| 45 | + """ |
| 46 | + Creates a Databricks instance pool. |
| 47 | +
|
| 48 | + The specification for the request json can be found at |
| 49 | + https://docs.databricks.com/api/latest/instance-pools.html#create |
| 50 | + """ |
| 51 | + json_cli_base(json_file, json, |
| 52 | + lambda json: InstancePoolsApi(api_client).create_instance_pool(json)) |
| 53 | + |
| 54 | + |
| 55 | +@click.command(context_settings=CONTEXT_SETTINGS) |
| 56 | +@click.option('--json-file', default=None, type=click.Path(), |
| 57 | + help='File containing JSON request to POST to /api/2.0/instance-pools/edit.') |
| 58 | +@click.option('--json', default=None, type=JsonClickType(), |
| 59 | + help=JsonClickType.help('/api/2.0/instance-pools/edit')) |
| 60 | +@debug_option |
| 61 | +@profile_option |
| 62 | +@eat_exceptions |
| 63 | +@provide_api_client |
| 64 | +def edit_cli(api_client, json_file, json): |
| 65 | + """ |
| 66 | + Edits a Databricks instance pool. |
| 67 | +
|
| 68 | + The specification for the request json can be found at |
| 69 | + https://docs.databricks.com/api/latest/instance-pools.html#edit |
| 70 | + """ |
| 71 | + if not bool(json_file) ^ bool(json): |
| 72 | + raise RuntimeError('Either --json-file or --json should be provided') |
| 73 | + json_cli_base(json_file, json, |
| 74 | + lambda json: InstancePoolsApi(api_client).edit_instance_pool(json), |
| 75 | + print_response=False) |
| 76 | + |
| 77 | + |
| 78 | +@click.command(context_settings=CONTEXT_SETTINGS) |
| 79 | +@click.option('--instance-pool-id', required=True, type=InstancePoolIdClickType(), |
| 80 | + help=InstancePoolIdClickType.help) |
| 81 | +@debug_option |
| 82 | +@profile_option |
| 83 | +@eat_exceptions |
| 84 | +@provide_api_client |
| 85 | +def delete_cli(api_client, instance_pool_id): |
| 86 | + """ |
| 87 | + Deletes a Databricks instance pool given its ID. |
| 88 | +
|
| 89 | + This permanently deletes the instance pool. The idle instances in the pool are terminated |
| 90 | + asynchronously. New clusters cannot attach to the pool. Running clusters attached to the pool |
| 91 | + continue to run but cannot auto-scale up. Terminated clusters attached to the pool will fail to |
| 92 | + start until they are edited to no longer use the pool. |
| 93 | + """ |
| 94 | + InstancePoolsApi(api_client).delete_instance_pool(instance_pool_id) |
| 95 | + |
| 96 | + |
| 97 | +@click.command(context_settings=CONTEXT_SETTINGS) |
| 98 | +@click.option('--instance-pool-id', required=True, type=InstancePoolIdClickType(), |
| 99 | + help=InstancePoolIdClickType.help) |
| 100 | +@debug_option |
| 101 | +@profile_option |
| 102 | +@eat_exceptions |
| 103 | +@provide_api_client |
| 104 | +def get_cli(api_client, instance_pool_id): |
| 105 | + """ |
| 106 | + Retrieves metadata about an instance pool. |
| 107 | + """ |
| 108 | + click.echo(pretty_format(InstancePoolsApi(api_client).get_instance_pool(instance_pool_id))) |
| 109 | + |
| 110 | + |
| 111 | +def _instance_pools_to_table(instance_pools_json): |
| 112 | + ret = [] |
| 113 | + stats_headers = ['idle_count', 'used_count', 'pending_idle_count', 'pending_used_count'] |
| 114 | + for c in instance_pools_json.get('instance_pools', []): |
| 115 | + pool_stats = [] |
| 116 | + pool_stats.append(c['instance_pool_id']) |
| 117 | + pool_stats.append(truncate_string(c['instance_pool_name'])) |
| 118 | + for header in stats_headers: |
| 119 | + pool_stats.append(c['stats'][header]) |
| 120 | + # clone the content in the pool_stats. Pool_stats will be re-used in next iteration. |
| 121 | + ret.append(pool_stats[:]) |
| 122 | + return ret |
| 123 | + |
| 124 | + |
| 125 | +@click.command(context_settings=CONTEXT_SETTINGS, |
| 126 | + short_help='Lists active and recently terminated instance pools.') |
| 127 | +@click.option('--output', default=None, help=OutputClickType.help, type=OutputClickType()) |
| 128 | +@debug_option |
| 129 | +@profile_option |
| 130 | +@eat_exceptions |
| 131 | +@provide_api_client |
| 132 | +def list_cli(api_client, output): |
| 133 | + """ |
| 134 | + Lists active instance pools with the stats of the pools. |
| 135 | + """ |
| 136 | + instance_pools_json = InstancePoolsApi(api_client).list_instance_pools() |
| 137 | + if OutputClickType.is_json(output): |
| 138 | + click.echo(pretty_format(instance_pools_json)) |
| 139 | + else: |
| 140 | + headers = ['ID', 'NAME', 'IDLE INSTANCES', 'USED INSTANCES', 'PENDING IDLE INSTANCES', |
| 141 | + 'PENDING USED INSTANCES'] |
| 142 | + click.echo(tabulate(_instance_pools_to_table(instance_pools_json), headers=headers, |
| 143 | + tablefmt='plain', numalign='left')) |
| 144 | + |
| 145 | + |
| 146 | +@click.group(context_settings=CONTEXT_SETTINGS, |
| 147 | + short_help='Utility to interact with Databricks instance pools.') |
| 148 | +@click.option('--version', '-v', is_flag=True, callback=print_version_callback, |
| 149 | + expose_value=False, is_eager=True, help=version) |
| 150 | +@debug_option |
| 151 | +@profile_option |
| 152 | +@eat_exceptions |
| 153 | +def instance_pools_group(): |
| 154 | + """ |
| 155 | + Utility to interact with Databricks instance pools. |
| 156 | + """ |
| 157 | + pass |
| 158 | + |
| 159 | + |
| 160 | +instance_pools_group.add_command(create_cli, name='create') |
| 161 | +instance_pools_group.add_command(edit_cli, name='edit') |
| 162 | +instance_pools_group.add_command(delete_cli, name='delete') |
| 163 | +instance_pools_group.add_command(get_cli, name='get') |
| 164 | +instance_pools_group.add_command(list_cli, name='list') |
0 commit comments