bodosdk 2.3.2
Bodo Platform SDK 2.3.2
Requires Python: >=3.8

# Bodo Platform SDK

Bodo Platform SDK is a Python library that provides a simple way to interact with the Bodo Platform API. It allows you
to create, manage, and monitor resources such as clusters, jobs, and workspaces.

## Updates:

- NEW:
  - Implementation of cursor.describe
- FIXES:
  - Update of cursor interface, added missing properties/methods:
    - rownumber
    - query_id
    - close

## Getting Started

### Installation

```shell
pip install bodosdk
```

### Creating workspace client

First you need to access your workspace in `https://platform.bodo.ai/` and create an _API Token_ in the Bodo Platform
for
Bodo SDK authentication.

Navigate to _API Tokens_ in the Admin Console to generate a token.
Copy and save the token's _Client ID_ and _Secret Key_ and use them to define a client (`BodoClient`) that can interact
with the Bodo Platform.

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient(
    client_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    secret_key="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
)
```

Alternatively, set `BODO_CLIENT_ID` and `BODO_SECRET_KEY` environment variables
to avoid requiring keys:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
```

To get workspace data, you can access the `workspace_data` attribute of the client:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
print(my_workspace.workspace_data)
```

### Additional Configuration Options for `BodoClient`

- `print_logs`: defaults to False. All API requests and responses are printed to the console if set to True.

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient(print_logs=True)
```

### Create first cluster

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='My first cluster',
    instance_type='c5.large',
    workers_quantity=1
)
```

Above example creates a simple one node cluster, with latest bodo version available and returns cluster object.
Platform will create cluster in your workspace.

### Waiting for status

To wait till cluster will be ready for interaction you can call
method `wait_for_status`

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='My first cluster',
    instance_type='c5.large',
    workers_quantity=1
)
my_cluster.wait_for_status(['RUNNING'])
```

This method will wait until any of provided statuses will occur or `FAILED` status will be set in case of some failure.
Check your workspace on `https://platform.bodo.ai/` and you will see your cluster, you can use Notebook to connect with
it.

### Updating Cluster

Now let's update our cluster, on `RUNNING` cluster you can update `name`, `description`, `auto_pause`, `auto_stop`
and `workers_quantity`(this will trigger scaling) only:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='My first cluster',
    instance_type='c5.large',
    workers_quantity=1
)
my_cluster.wait_for_status(['RUNNING'])
my_cluster.update(
    description='My description',
    name="My updated cluster",
    auto_pause=15,
    auto_stop=30
)
```

All other modifcations like `instance_type`, `bodo_version` etc need `STOPPED` cluster

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.get("cluster_id")
if my_cluster.status != 'STOPPED':
    my_cluster.stop(wait=True)
my_cluster.update(instance_type='c5.2xlarge', workers_quantity=2)
```

### Create First Job

On running cluster you can schedule a job in very simple way:
First on `https://platform.bodo.ai` navigate to notebook in your workspace and
create following `test.py` file in your main directory:

```python
import pandas as pd
import numpy as np
import bodo
import time

NUM_GROUPS = 30
NUM_ROWS = 20_000_000

df = pd.DataFrame({
    "A": np.arange(NUM_ROWS) % NUM_GROUPS,
    "B": np.arange(NUM_ROWS)
})
df.to_parquet("my_data.pq")
time.sleep(1) # wait till file will be available on all nodes
@bodo.jit(cache=True)
def computation():
    t1 = time.time()
    df = pd.read_parquet("my_data.pq")
    df1 = df[df.B > 4].A.sum()
    print("Execution time:", time.time() - t1)
    return df1

result = computation()
print(result)
```

then define job on cluster through SDK, wait till `SUCCEEDED` and check logs

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.get("cluster_id")
my_job = my_cluster.run_job(
    code_type='PYTHON',
    source={'type': 'WORKSPACE', 'path': '/'},
    exec_file='test.py'
)
print(my_job.wait_for_status(['SUCCEEDED']).get_stdout())
```

You can use almost same confiuration to run SQL file, all you need is to define your `test.sql` file and Catalog `https://platform.bodo.ai`:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.get("cluster_id")
my_job = my_cluster.run_job(
    code_type='SQL',
    source={'type': 'WORKSPACE', 'path': '/'},
    exec_file='test.sql',
    catalog="MyCatalog"
)
print(my_job.wait_for_status(['SUCCEEDED']).get_stdout())

```

### Cluster List and executing jobs on it's elements

Now let's try to run same job on different clusters:

```python
from bodosdk import BodoWorkspaceClient
import random

my_workspace = BodoWorkspaceClient()

random_val = random.random() # just to avoid conflicts on name
clusters_conf = [('c5.large', 8), ('c5.xlarge',4), ('c5.2xlarge',2)]
for  i, conf in enumerate(clusters_conf):
    my_workspace.ClusterClient.create(
        name=f'Test {i}',
        instance_type=conf[0],
        workers_quantity=conf[1],
        custom_tags={'test_tag': f'perf_test{random_val}'} # let's add tag to easy filter our clusters
    )
# get list by tag
clusters = my_workspace.ClusterClient.list(filters={
    'tags': {'test_tag': f'perf_test{random_val}'}
})
# run same job 3 times, once per each cluster
jobs = clusters.run_job(
    code_type='PYTHON',
    source={'type': 'WORKSPACE', 'path': '/'},
    exec_file='test.py'
)
#wait for jobs to finish and print results
for job in jobs.wait_for_status(['SUCCEEDED']):
    print(job.name, job.cluster.name)
    print(job.get_stdout())
#remove our clusters
jobs.clusters.delete() # or clusters.delete()
```

### Execute SQL query

You can also execute SQL queries by passing just query text like following:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_sql_job = my_workspace.JobClient.run_sql_query(sql_query="SELECT 1", catalog="MyCatalog", cluster={
    "name": 'Temporary cluster',
    "instance_type": 'c5.large',
    "workers_quantity": 1
})
print(my_sql_job.wait_for_status(['SUCCEEDED']).get_stdout())
```

In above case, when you provide cluster configuration but not existing cluster it will be terminated as soon
as SQL job will finish.

If you want to execute sql job on existing cluster just use `run_sql_query` on cluster:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='My cluster',
    instance_type='c5.large',
    workers_quantity=1
)
my_sql_job = my_cluster.run_sql_query(sql_query="SELECT 1", catalog="MyCatalog")
print(my_sql_job.wait_for_status(['SUCCEEDED']).get_stdout())
```

### Connector

You can also execute SQL queries using connector for cluster:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='My cluster',
    instance_type='c5.large',
    workers_quantity=1
)
connection = my_cluster.connect('MyCatalog') # or connection = my_workspace.ClusterClient.connect('MyCatalog', 'cluster_id')
print(connection.cursor().execute("SELECT 1").fetchone())
my_cluster.delete()
```

### Job Templates

Against defining jobs from scratch you can create a template for your jobs, and then easily run them, e.g.:

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
tpl = my_workspace.JobTemplateClient.create(
    name='My template',
    cluster={
        'instance_type': 'c5.xlarge',
        'workers_quantity': 1
    },
    code_type="SQL",
    catalog="MyCatalog",
    exec_text="SELECT 1"
)
job1 = tpl.run() # you can simply run it
job2 = tpl.run(exec_text="SELECT 2") # or run it with overriding template values
job3 = tpl.run(cluster={'instance_type': 'c5.large'}) # you can override even part of cluster configuration

jobs = my_workspace.JobClient.list(filters={'template_ids':[tpl.id]}) # you can filter jobs by it's template_id
for job in jobs.wait_for_status(['SUCCEEDED']):
    print(job.name, job.cluster.instance_type, job.get_stdout())

```

You can also run your template on specific cluster e.g:

```python
from bodosdk import BodoWorkspaceClient
from bodosdk.models import JobTemplateFilter

my_workspace = BodoWorkspaceClient()
tpls = my_workspace.JobTemplateClient.list(filters=JobTemplateFilter(names=['My template']))
my_cluster = my_workspace.ClusterClient.create(
    name='My cluster',
    instance_type='c5.large',
    workers_quantity=1
)
print(my_cluster.run_job(template_id=tpls[0].id).wait_for_status(['SUCCEEDED']).get_stdout())
my_cluster.delete()
```

### Scheduled Jobs

Rather than having to setup your own infrastructure or scheduler, you can create a scheduled job using the Bodo Platform. You will have to create a Job Template first.

```python
from bodosdk import BodoWorkspaceClient
my_workspace = BodoWorkspaceClient()
tpl = my_workspace.JobTemplateClient.create(
    name='My template',
    cluster={
        'instance_type': 'c5.xlarge',
        'workers_quantity': 1
    },
    code_type="SQL",
    catalog="MyCatalog",
    exec_text="SELECT 1"
)
scheduled_job = my_workspace.CronJobClient.create(
    name="Cron job",
    schedule="0 * * * *",
    timezone="Etc/GMT",
    max_concurrent_runs=1,
    job_template=tpl,
)
```
Job Runs using the job template that you provided will be automatically created and execute based on the provided schedule.

## Statuses

Each resource, Cluster, Job or Workspace has own set of statuses which are following:

### Cluster:

- NEW
- INPROGRESS
- PAUSING
- PAUSED
- STOPPING
- STOPPED
- INITIALIZING
- RUNNING
- FAILED
- TERMINATED

### Job:

- PENDING
- RUNNING
- SUCCEEDED
- FAILED
- CANCELLED
- CANCELLING
- TIMEOUT

### Workspace:

- NEW
- INPROGRESS
- READY
- FAILED
- TERMINATING
- TERMINATED

## Organization client and workspaces:

To manage workspaces you need different keys (generated for organization) and differenct SDK client, for start let's list
all our workspaces:

```python
from bodosdk import BodoOrganizationClient

my_org = BodoOrganizationClient(
    client_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    secret_key="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
) # or BodoOrganizationClient() if `BODO_ORG_CLIENT_ID` and `BODO_ORG_SECRET_KEY` are exported
for w in my_org.list_workspaces():
    print(w.name)
```

You can filter workspaces providing valid filters:

```python
from bodosdk import BodoOrganizationClient
from bodosdk.models import WorkspaceFilter
my_org = BodoOrganizationClient()

for w in my_org.list_workspaces(filters=WorkspaceFilter(statuses=['READY'])):
    print(w.name)
```

You can provide filters as 'WorkspaceFilter' imported from `bodosdk.models` or as a dictionary:

```python
from bodosdk import BodoOrganizationClient
my_org = BodoOrganizationClient()

for w in my_org.list_workspaces(filters={"statuses": ['READY']}):
    print(w.name)
```

### Create new Workspace

```python
from bodosdk import BodoOrganizationClient
my_org = BodoOrganizationClient()
my_workspace = my_org.create_workspace(
    name="SDK test",
    region='us-east-2',
    cloud_config_id="a0d1242c-3091-42de-94d9-548e2ae33b73",
    storage_endpoint_enabled=True
).wait_for_status(['READY'])
assert my_workspace.id == my_org.list_workspaces(filters={"names": ['SDK test'], "statuses": ['READY']})[0].id
my_workspace.delete() # remove workspace at the end
```

### Upgrade workspace infra

In some cases when you have workspace existing for a long time you may want to re-run terraform to
apply fresh changes to workspace infrastructure. You can do it following way:

```python
from bodosdk import BodoOrganizationClient
my_org = BodoOrganizationClient()
my_org.list_workspaces(filters={'ids': ['workspace_to_update1_id', 'workspace_to_update2_id']}).update_infra()
```

# Advanced

In this section we will present more examples of bodosdk usages.

## Workspace created in existing VPC

There is possibility to create workspace on existing infrastructure. The only requirement is that VPC need access to
Internet, either NAT or IGW. It's needed to allow clusters to authorize in external auth service.

```python
from bodosdk import BodoOrganizationClient
my_org = BodoOrganizationClient()
my_workspace = my_org.create_workspace(
    cloud_config_id="cloudConfigId",
    name="My workspace",
    region="us-east-1",
    storage_endpoint_enabled=True,
    vpc_id="existing-vpc-id",
    private_subnets_ids=['subnet1', 'subnet2'],
    public_subnets_ids=['subnet3']
)
my_workspace.wait_for_status(['READY'])
```

## Spot instances, auto AZ

You can create Cluster using spot instances, to reduce cost of usage, downside is that you cannot PAUSE
this kind of cluster, and from time to time cluster may be unavailable (when spot instance is released).

Auto AZ is mechanism which retries cluster creation in another AZ, when in current AZ
there is no enough instances of desired type.

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.create(
    name='Spot cluster',
    instance_type='c5.large',
    workers_quantity=1,
    use_spot_instance=True,
    auto_az=True,
)
```

## Accelerated networking

Accelerated networking is enabled by for instances that supporting.

You can get list of all supported instances using ClusterClient, it returns list of
InstanceType objects. Field `accelerated_networking` informs about network acceleration.

```python
from bodosdk import BodoWorkspaceClient

my_workspace = BodoWorkspaceClient()

accelerated_networking_instances = [x for x in my_workspace.ClusterClient.get_instances() if x.accelerated_networking]

my_cluster = my_workspace.ClusterClient.create(
    name='Spot cluster',
    instance_type=accelerated_networking_instances[0].name,
    workers_quantity=1,
)
```

## Preparing clusters for future use:

In Bodo, Cluster may be in two states responsible for suspended status: `PAUSED` and `STOPPED`.
Spot clusters cannot be `PAUSED`. There are 3 differences between those states: cost, start up time, error rate.

### Costs

`PAUSED` > `STOPPED` - In `PAUSED` state we are paying for disks while in `STOPPED` we don't.

### Start up time

`STOPPED` > `PAUSED` - Bringing back machines in `PAUSED` state is much faster, as those machines are already
defined in cloud

### Error rate

`PAUSED` > `STOPPED` - By error rate we mean situation when number of available instances of descired types is lower
than number of requested workers. As in `PAUSED` state, instance entities are already defined,
and we request for reesources at once it's more likely to happen than in `STOPPED` state,
where asg is maintaining instance creation and it waits for available resources.

Prepare clusters for further use and make them `PAUSED`

```python
from bodosdk import BodoWorkspaceClient
from bodosdk.models import ClusterFilter
my_workspace = BodoWorkspaceClient()

clusters_conf = {
    'Team A': {
        'instance_type': 'c5.2xlarge',
        'workers': 4,
    },
    'Team b': {
        'instance_type': 'c5.xlarge',
        'workers': 2,
    },
    'Team C': {
        'instance_type': 'c5.16xlarge',
        'workers': 2,
    }
}
for owner, conf in clusters_conf.items():
    my_workspace.ClusterClient.create(
        name = f"{owner} Cluster",
        instance_type=conf['instance_type'],
        workers_quantity=conf['workers'],
        custom_tags={'owner': owner, 'purpose': 'test'}
    )

my_workspace.ClusterClient.list(
    filters=ClusterFilter(tags={'purpose': 'test'})
).wait_for_status(
    ['RUNNING', 'INITIALIZING']
).pause().wait_for_status(['PAUSED'])
```

## Use another cluster as a template for cluster definition in job

Let's imagine that you have a cluster (in any state) and you wan't to run job on the same specification, but you don't
want to use previously defined cluster. You can do following

```python
from bodosdk import BodoWorkspaceClient
my_workspace = BodoWorkspaceClient()
my_cluster = my_workspace.ClusterClient.get('existing_cluster')
cluster_conf = my_cluster.dict()
del cluster_conf['uuid']
my_sql_job = my_workspace.JobClient.run_sql_query(sql_query="SELECT 1", catalog="MyCatalog", cluster=cluster_conf)
```

In that case job will create a new cluster with provided configuration, executes and after job is finished
removes cluster.


 #INDEX 

# bodosdk package contents

<a id="module-bodosdk.clients.cluster"></a>

### *class* bodosdk.clients.cluster.ClusterClient(workspace_client: IBodoWorkspaceClient)

Bases: `IClusterClient`

A client for managing cluster operations in a Bodo workspace.

#### \_deprecated_methods

A dictionary of deprecated methods.

* **Type:**
  Dict

#### \_images

A list of available Bodo images.

* **Type:**
  List[IBodoImage]

* **Parameters:**
  **workspace_client** (*IBodoWorkspaceClient*) – The workspace client used for operations.

#### *property* Cluster *: [Cluster](#bodosdk.models.cluster.Cluster)*

Provides access to cluster operations.

* **Returns:**
  An instance of Cluster for cluster operations.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### *property* ClusterList *: [ClusterList](#bodosdk.models.cluster.ClusterList)*

Provides access to listing clusters.

* **Returns:**
  An instance of ClusterListAPIModel for listing clusters.
* **Return type:**
  [ClusterList](#bodosdk.models.cluster.ClusterList)

#### connect(catalog: str, cluster_id: str)

Connect to a specific catalog and cluster.

* **Parameters:**
  * **catalog** – The name the catalog to connect to.
  * **cluster_id** – The UUID of the cluster to connect to.
* **Returns:**
  An instance of Connection representing the connection to the catalog and cluster.

#### create(name: str, instance_type: str = None, workers_quantity: int = None, description: str | None = None, bodo_version: str | None = None, auto_stop: int | None = None, auto_pause: int | None = None, auto_upgrade: bool | None = None, auto_az: bool | None = None, use_spot_instance: bool | None = None, aws_deployment_subnet_id: str | None = None, availability_zone: str | None = None, instance_role: [InstanceRole](#bodosdk.models.instance_role.InstanceRole) | Dict | None = None, custom_tags: Dict | None = None)

Creates a new cluster with the specified configuration.

* **Parameters:**
  * **name** (*str*) – The name of the cluster.
  * **instance_type** (*str* *,* *optional*) – The type of instance to use for the cluster nodes.
  * **workers_quantity** (*int* *,* *optional*) – The number of worker nodes in the cluster.
  * **description** (*str* *,* *optional*) – A description of the cluster.
  * **bodo_version** (*str* *,* *optional*) – The Bodo version to use for the cluster.
    If not provided, the latest version is used.
  * **auto_stop** (*int* *,* *optional*) – The auto-stop time in minutes for the cluster.
  * **auto_pause** (*int* *,* *optional*) – The auto-pause time in minutes for the cluster.
  * **auto_upgrade** (*bool* *,* *optional*) – Should the cluster be automatically upgraded to
    the latest Bodo version on restart.
  * **auto_az** (*bool* *,* *optional*) – Whether to automatically select the availability zone.
  * **use_spot_instance** (*bool* *,* *optional*) – Whether to use spot instances for the cluster.
  * **aws_deployment_subnet_id** (*str* *,* *optional*) – The AWS deployment subnet ID.
  * **availability_zone** (*str* *,* *optional*) – The availability zone for the cluster.
  * **instance_role** ([*InstanceRole*](#bodosdk.models.instance_role.InstanceRole) *|* *Dict* *,* *optional*) – The instance role or a custom role configuration.
  * **custom_tags** (*Dict* *,* *optional*) – Custom tags to assign to the cluster resources.
* **Returns:**
  The created Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### get(id: str)

Retrieves a cluster by its ID.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to retrieve.
* **Returns:**
  The retrieved Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### get_bodo_versions()

Retrieves a list of available Bodo versions.

* **Returns:**
  A list of available Bodo versions.
* **Return type:**
  List[str]

#### get_images()

Retrieves a list of available images.

* **Returns:**
  A list of image IDs available for clusters.
* **Return type:**
  List[str]

#### get_instance_types()

Retrieves list of all supported instance types

* **Returns:**
  List[InstanceType]

#### *property* latest_bodo_version *: str*

Retrieves the latest Bodo version available.

* **Returns:**
  The latest Bodo version.
* **Return type:**
  str

#### list(filters: Dict | [ClusterFilter](#bodosdk.models.cluster.ClusterFilter) | None = None, order: Dict | None = None)

Lists clusters based on the provided filters and order.

* **Parameters:**
  * **filters** (*Dict* *|* [*ClusterFilter*](#bodosdk.models.cluster.ClusterFilter) *,* *optional*) – The filters to apply to the cluster listing.
  * **order** (*Dict* *,* *optional*) – The order in which to list the clusters.
* **Returns:**
  A list of clusters matching the criteria.
* **Return type:**
  [ClusterList](#bodosdk.models.cluster.ClusterList)

#### pause(id: str, wait=False)

Pauses the specified cluster.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to pause.
* **Returns:**
  The paused Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### remove(id: str, wait=False)

Removes the specified cluster.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to remove.
* **Returns:**
  None

#### resume(id: str, wait=False)

Resumes the specified paused cluster.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to resume.
* **Returns:**
  The resumed Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### scale(id: str, new_size: int)

Scales the specified cluster to the new size.

* **Parameters:**
  * **id** (*str*) – The ID of the cluster to scale.
  * **new_size** (*int*) – The new size for the cluster in terms of the number of worker nodes.
* **Returns:**
  The scaled Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### start(id: str, wait=False)

Starts the specified stopped cluster.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to start.
* **Returns:**
  The started Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### stop(id: str, wait=False)

Stops the specified cluster.

* **Parameters:**
  **id** (*str*) – The ID of the cluster to stop.
* **Returns:**
  The stopped Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### update(id: str, name: str | None = None, description: str | None = None, auto_stop: int | None = None, auto_pause: int | None = None, auto_upgrade: bool | None = True, workers_quantity: int | None = None, instance_role: [InstanceRole](#bodosdk.models.instance_role.InstanceRole) | Dict | None = None, instance_type: str | None = None, bodo_version: str | None = None, auto_az: bool | None = None, availability_zone: str | None = None, custom_tags: Dict | None = None)

Updates the specified cluster with the given configuration.

* **Parameters:**
  * **id** (*str*) – The ID of the cluster to update.
  * **name** (*str* *,* *optional*) – The new name for the cluster.
  * **description** (*str* *,* *optional*) – A new description for the cluster.
  * **auto_stop** (*int* *,* *optional*) – The new auto-stop time in minutes.
  * **auto_pause** (*int* *,* *optional*) – The new auto-pause time in minutes.
  * **auto_upgrade** (*bool* *,* *optional*) – if cluster should be updated after each restart.
  * **workers_quantity** (*int* *,* *optional*) – The new number of worker nodes.
  * **instance_role** ([*InstanceRole*](#bodosdk.models.instance_role.InstanceRole) *|* *Dict* *,* *optional*) – The new instance role or custom role configuration.
  * **instance_type** (*str* *,* *optional*) – The new instance type for the cluster nodes.
  * **bodo_version** (*str* *,* *optional*) – The new Bodo version for the cluster.
  * **auto_az** (*bool* *,* *optional*) – Whether to automatically select the availability zone.
  * **availability_zone** (*str* *,* *optional*) – The new availability zone for the cluster.
  * **custom_tags** (*Dict* *,* *optional*) – New custom tags for the cluster resources.
* **Returns:**
  The updated Cluster object.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

#### wait_for_status(id: str, statuses: List, timeout: int | None = 300, tick: int | None = 30)

Waits for the specified cluster to reach any of the given statuses within the timeout period.

* **Parameters:**
  * **id** (*str*) – The ID of the cluster to monitor.
  * **statuses** (*List*) – The list of statuses to wait for.
  * **timeout** (*int* *,* *optional*) – The timeout period in seconds.
  * **tick** (*int* *,* *optional*) – The interval in seconds between status checks.
* **Returns:**
  The Cluster object if it reaches the desired status within the timeout period.
* **Return type:**
  [Cluster](#bodosdk.models.cluster.Cluster)

<a id="module-bodosdk.clients.instance_role"></a>

### *class* bodosdk.clients.instance_role.InstanceRoleClient(workspace_client: IBodoWorkspaceClient)

Bases: `IInstanceRoleClient`

#### *property* InstanceRole *: [InstanceRole](#bodosdk.models.instance_role.InstanceRole)*

Get the InstanceRole object.

* **Returns:**
  An instance of InstanceRole.
* **Return type:**
  [InstanceRole](#bodosdk.models.instance_role.InstanceRole)

#### *property* InstanceRoleList *: [InstanceRoleList](#bodosdk.models.instance_role.InstanceRoleList)*

Get the InstanceRoleList object.

* **Returns:**
  An instance of InstanceRoleList.
* **Return type:**
  [InstanceRoleList](#bodosdk.models.instance_role.InstanceRoleList)

#### create(role_arn: str, description: str, name: str = None)

Create a new instance role.

* **Parameters:**
  * **role_arn** (*str*) – The ARN of the role.
  * **description** (*str*) – A description of the role.
  * **name** (*str* *,* *optional*) – The name of the role. Defaults to None.
* **Returns:**
  The created instance role after saving.
* **Return type:**
  [InstanceRole](#bodosdk.models.instance_role.InstanceRole)

#### delete(id: str)

Delete an instance role by its ID.

* **Parameters:**
  **id** (*str*) – The UUID of the instance role to delete.

#### get(id: str)

Get an instance role by its ID.

* **Parameters:**
  **id** (*str*) – The UUID of the instance role.
* **Returns:**
  An instance of InstanceRole.
* **Return type:**
  [InstanceRole](#bodosdk.models.instance_role.InstanceRole)

#### list(filters: Dict | [InstanceRoleFilter](#bodosdk.models.instance_role.InstanceRoleFilter) | None = None, order: Dict | None = None)

List all instance roles with optional filters and order.

* **Parameters:**
  * **filters** (*Optional* *[**Union* *[**Dict* *,* [*InstanceRoleFilter*](#bodosdk.models.instance_role.InstanceRoleFilter) *]* *]*) – A dictionary or InstanceRoleFilter
  * **filters.** (*object to apply*) –
  * **order** (*Optional* *[**Dict* *]*) – A dictionary to specify the order of the results.
* **Returns:**
  An instance of InstanceRoleList containing the filtered and ordered instance roles.
* **Return type:**
  [InstanceRoleList](#bodosdk.models.instance_role.InstanceRoleList)

<a id="module-bodosdk.clients.job"></a>

### *class* bodosdk.clients.job.JobClient(workspace_client: IBodoWorkspaceClient)

Bases: `IJobClient`

#### *property* JobRun *: [JobRun](#bodosdk.models.job.JobRun)*

Get the JobRun object.

* **Returns:**
  An instance of JobRun.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

#### *property* JobRunList *: [JobRunList](#bodosdk.models.job.JobRunList)*

Get the JobRunList object.

* **Returns:**
  An instance of JobRunList.
* **Return type:**
  [JobRunList](#bodosdk.models.job.JobRunList)

#### cancel_job(id: str)

Cancel job by id.

* **Parameters:**
  **id** (*str*) – Job id.
* **Returns:**
  Job object.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

#### cancel_jobs(filters: Dict | [JobFilter](#bodosdk.models.job.JobFilter) | None = None)

Cancel jobs with the given filters.

* **Parameters:**
  **filters** (*Optional* *[**Union* *[**Dict* *,* [*JobFilter*](#bodosdk.models.job.JobFilter) *]* *]*) – Filters to apply on the list.
* **Returns:**
  JobRunList object.
* **Return type:**
  [JobRunList](#bodosdk.models.job.JobRunList)

#### get(id: str)

Get job by id.

* **Parameters:**
  **id** (*str*) – Job id.
* **Returns:**
  Job object.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

#### list(filters: Dict | [JobFilter](#bodosdk.models.job.JobFilter) | None = None, order: Dict | None = None)

List jobs with the given filters.

* **Parameters:**
  * **filters** (*Optional* *[**Union* *[**Dict* *,* [*JobFilter*](#bodosdk.models.job.JobFilter) *]* *]*) – Filters to apply on the list.
  * **order** (*Optional* *[**Dict* *]*) – Order to apply on the list.
* **Returns:**
  JobRunList object.
* **Return type:**
  [JobRunList](#bodosdk.models.job.JobRunList)

#### run(template_id: str = None, cluster: dict | ICluster = None, code_type: str = None, source: dict | IS3Source | IGitRepoSource | IWorkspaceSource | ITextSource = None, exec_file: str = None, exec_text: str = None, args: Sequence[Any] | Dict | str = None, env_vars: dict = None, timeout: int = None, num_retries: int = None, delay_between_retries: int = None, retry_on_timeout: bool = None, name: str = None, catalog: str = None, store_result: bool = None)

Run a job with the given parameters.

* **Parameters:**
  * **template_id** (*str*) – Job template id.
  * **cluster** (*Union* *[**dict* *,* *ICluster* *]*) – Cluster object or cluster config.
  * **code_type** (*str*) – Code type.
  * **source** (*Union* *[**dict* *,* *IS3Source* *,* *IGitRepoSource* *,* *IWorkspaceSource* *,* *ITextSource* *]*) – Source object.
  * **exec_file** (*str*) – Exec file path.
  * **exec_text** (*str*) – Exec text.
  * **args** (*Union* *[**Sequence* *[**Any* *]* *,* *Dict* *,* *str* *]*) – Arguments.
  * **env_vars** (*dict*) – Environment variables.
  * **timeout** (*int*) – Timeout.
  * **num_retries** (*int*) – Number of retries.
  * **delay_between_retries** (*int*) – Delay between retries.
  * **retry_on_timeout** (*bool*) – Retry on timeout.
  * **name** (*str*) – Job name.
  * **catalog** (*str*) – Catalog, applicable only for SQL jobs.
  * **store_result** (*bool*) – Whether to store the result.
* **Returns:**
  Job object.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

#### run_sql_query(template_id: str = None, catalog: str = None, sql_query: str = None, cluster: dict | ICluster = None, name: str = None, args: Sequence[Any] | Dict = None, timeout: int = None, num_retries: int = None, delay_between_retries: int = None, retry_on_timeout: bool = None, store_result: bool = True)

Run a SQL job with the given parameters.

* **Parameters:**
  * **template_id** (*str*) – Job template id.
  * **catalog** (*str*) – Catalog.
  * **sql_query** (*str*) – SQL query.
  * **cluster** (*Union* *[**dict* *,* *ICluster* *]*) – Cluster object or cluster config.
  * **name** (*str*) – Job name.
  * **args** (*Union* *[**Sequence* *[**Any* *]* *,* *Dict* *]*) – Arguments.
  * **timeout** (*int*) – Timeout.
  * **num_retries** (*int*) – Number of retries.
  * **delay_between_retries** (*int*) – Delay between retries.
  * **retry_on_timeout** (*bool*) – Retry on timeout.
  * **store_result** (*bool*) – Whether to store the result.
* **Returns:**
  Job object.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

#### wait_for_status(id: str, statuses: List[str], timeout: int = 3600, tick: int = 30)

Wait for job to reach one of the given statuses.

* **Parameters:**
  * **id** (*str*) – Job id.
  * **statuses** (*List* *[**str* *]*) – List of statuses to wait for.
  * **timeout** (*int*) – Timeout.
  * **tick** (*int*) – Tick.
* **Returns:**
  Job object.
* **Return type:**
  [JobRun](#bodosdk.models.job.JobRun)

<a id="module-bodosdk.clients.job_tpl"></a>

### *class* bodosdk.clients.job_tpl.JobTemplateClient(workspace_client: IBodoWorkspaceClient)

Bases: `IJobTemplateClient`

#### *property* JobTemplate *: [JobTemplate](#bodosdk.models.job.JobTemplate)*

#### *property* JobTemplateList *: [JobTemplateList](#bodosdk.models.job.JobTemplateList)*

#### create(name: str = None, description: str = None, cluster: dict | ICluster = None, code_type: str = None, source: dict | IS3Source | IGitRepoSource | IWorkspaceSource | ITextSource = None, exec_file: str = None, exec_text: str = None, args: dict | str = None, env_vars: dict = None, timeout: int = None, num_retries: int = None, delay_between_retries: int = None, retry_on_timeout: bool = None, catalog: str = None, store_result: bool = False)

Create a new job template with the given parameters.

* **Parameters:**
  * **name** (*str*) – Name of the job template.
  * **description** (*str*) – Description of the job template.
  * **cluster** (*Union* *[**dict* *,* *ICluster* *]*) – Cluster object or cluster config.
  * **code_type** (*str*) – Code type.
  * **source** (*Union* *[**dict* *,* *IS3Source* *,* *IGitRepoSource* *,* *IWorkspaceSource* *,* *ITextSource* *]*) – Source object.
  * **exec_file** (*str*) – Exec file path.
  * **exec_text** (*str*) – Exec text.
  * **args** (*Union* *[**dict* *,* *str* *]*) – Arguments.
  * **env_vars** (*dict*) – Environment variables.
  * **timeout** (*int*) – Timeout.
  * **num_retries** (*int*) – Number of retries.
  * **delay_between_retries** (*int*) – Delay between retries.
  * **retry_on_timeout** (*bool*) – Retry on timeout.
  * **catalog** (*str*) – Catalog, applicable only for SQL code type.
  * **store_result** (*bool*) – Whether to store the result.

#### get(id: str)

Get job template by id.

* **Parameters:**
  **id** (*str*) – Job template id.
* **Returns:**
  Job template object.
* **Return type:**
  [JobTemplate](#bodosdk.models.job.JobTemplate)

#### list(filters: Dict = None)

List job templates with the given filters.

* **Parameters:**
  **filters** (*Dict*) – Filters to apply on the list.
* **Returns:**
  JobTemplateList object.
* **Return type:**
  [JobTemplateList](#bodosdk.models.job.JobTemplateList)

#### remove(id: str)

Delete job template by id.

* **Parameters:**
  **id** (*str*) – Job template id.

<a id="module-bodosdk_clients_cron-job_CronJobClient"></a>

### *class* bodosdk.clients.cron_job.CronJobClient(workspace_client: IBodoWorkspaceClient)

#### _deprecated_methods: Dict = {}

A dictionary of deprecated methods.

**Type:** Dict

#### property CronJob: [_CronJob_](#module-bodosdk_models_cron-job_CronJob)

Provides access to CronJob operations.

* **Return:** A CronJob instance for cron job operations.
* **Return Type:** [CronJob](#module-bodosdk_models_cron-job_CronJob)

#### property CronJobList: [_CronJobList_](#module-bodosdk_models_cron-job_CronJobList)

Provides access to a CronJob list.

* **Return:** A CronJobList instance for listing cron jobs.
* **Return Type:** [CronJobList](#module-bodosdk_models_cron-job_CronJobList)

#### list(order: Dict | None = None)

List cron jobs based on the provided order.

* **Parameters:**
  * **order** ( _Dict , optional_ ) – The order in which to list the cron jobs.
* **Return:** A list of cron jobs in the provided ordering.
* **Return Type:** [CronJobList](#module-bodosdk_models_cron-job_CronJobList)

#### get(id: str)

Get cron job by id.

* **Parameters:**
  * **id** ( _str_ ) – The ID of the cron job to retrieve.
* **Return:** The retrieved CronJob object.
* **Return Type:** [CronJob](#module-bodosdk_models_cron-job_CronJob)

#### create(name: str = None, description: str = None, schedule: str = None, timezone: str = "Etc/GMT", max_concurrent_runs: int = 1, job_template: IJobTemplate = None, cluster: Union[dict, ICluster] = None, pause_cluster_when_finished: bool = None)

Create a new cron job with the given parameters.

* **Parameters**:
  * **name** _(str)_ : Name of the cron job.
  * **description** _(str)_ : Description of the cron job.
  * **schedule** _(str)_ : Schedule the cron job should follow in UNIX cron syntax.
  * **timezone** _(str)_ : Timezone the cron job schedule should be based off of.
  * **max_concurrent_runs** _(int)_ : Maximum number of cron job runs that can happen concurrently (max is 10).
  * **job_template** _(IJobTemplate)_ : Job Template the cron job is derived from.
  * **cluster** _(Union[dict, ICluster])_ : Cluster object or cluster config.
  * **pause_cluster_when_finished** _(bool)_ : Whether to pause the cluster when the cron job run has finished. Note this is only used when passing a non-job-dedicated cluster.
* **Return:** The created CronJob object.
* **Return Type:** [CronJob](#module-bodosdk_models_cron-job_CronJob)

#### remove(id: str)

Delete cron job by id.

* **Parameters:**
  * **id** ( _str_ ) – The ID of the cron job to remove.
* **Return:** The status code of the response
* **Return Type:** int

<a id="module-bodosdk.clients.organization"></a>

### *class* bodosdk.clients.organization.BodoOrganizationClient(client_id=None, secret_key=None, api_url='https://api.bodo.ai/api', auth_url='https://auth.bodo.ai', print_logs=False)

Bases: `IBodoOrganizationClient`

#### *property* CloudConfig *: [CloudConfig](#bodosdk.models.cloud_config.CloudConfig)*

#### *property* CloudConfigList *: [CloudConfigList](#bodosdk.models.cloud_config.CloudConfigList)*

#### *property* Workspace *: [Workspace](#bodosdk.models.workspace.Workspace)*

#### *property* WorkspaceList *: [WorkspaceList](#bodosdk.models.workspace.WorkspaceList)*

#### create_aws_cloud_config(name: str, tf_backend_region: str, role_arn: str | None = None, tf_bucket_name: str | None = None, account_id: str | None = None, access_key_id: str | None = None, secret_access_key: str | None = None, custom_tags: dict | None = None)

Create a new AWS cloud config in the organization with the given parameters.

* **Parameters:**
  * **name** (*str*) – Name of the cloud config.
  * **tf_backend_region** (*str*) – Terraform backend region.
  * **role_arn** (*Optional* *[**str* *]*) – Role ARN.
  * **tf_bucket_name** (*Optional* *[**str* *]*) – Terraform bucket name.
  * **account_id** (*Optional* *[**str* *]*) – Account id.
  * **access_key_id** (*Optional* *[**str* *]*) – Access key id.
  * **secret_access_key** (*Optional* *[**str* *]*) – Secret access key.
  * **custom_tags** (*Optional* *[**dict* *]*) – Custom tags for the cloud config.
* **Returns:**
  CloudConfig object.
* **Return type:**
  [CloudConfig](#bodosdk.models.cloud_config.CloudConfig)

#### create_azure_cloud_config(name: str, tf_backend_region: str, tenant_id: str, subscription_id: str, resource_group: str, custom_tags: