Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ jobs:
echo "is_semantic_tag=$IS_SEMANTIC_TAG" >> $GITHUB_OUTPUT

- name: Upload image
uses: ishworkh/docker-image-artifact-upload@v1
uses: ishworkh/container-image-artifact-upload@v2.0.0
with:
image: "sapi-python-client"
image: ${{ env.APP_IMAGE }}
retention_days: "1"

tests_aws:
Expand All @@ -63,9 +63,9 @@ jobs:
uses: actions/checkout@v3

- name: Download image
uses: ishworkh/docker-image-artifact-download@v1
uses: ishworkh/container-image-artifact-download@v2.0.0
with:
image: "sapi-python-client"
image: ${{ env.APP_IMAGE }}

- name: Run Tests
run: |
Expand All @@ -80,9 +80,9 @@ jobs:
uses: actions/checkout@v3

- name: Download image
uses: ishworkh/docker-image-artifact-download@v1
uses: ishworkh/container-image-artifact-download@v2.0.0
with:
image: "sapi-python-client"
image: ${{ env.APP_IMAGE }}

- name: Run Tests
run: |
Expand All @@ -97,9 +97,9 @@ jobs:
uses: actions/checkout@v3

- name: Download image
uses: ishworkh/docker-image-artifact-download@v1
uses: ishworkh/container-image-artifact-download@v2.0.0
with:
image: "sapi-python-client"
image: ${{ env.APP_IMAGE }}

- name: Run Tests
run: |
Expand Down
11 changes: 11 additions & 0 deletions kbcstorage/branches.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,14 @@ def metadata(self, branch_id="default"):

url = f"{self.base_url}branch/{branch_id}/metadata"
return self._get(url)

def branch_detail(self, branch_id="default"):
"""
Get branch details
"""

if not isinstance(branch_id, str) or branch_id == "":
raise ValueError(f"Invalid branch_id '{branch_id}'")

url = f"{self.base_url}dev-branches/{branch_id}"
return self._get(url)
16 changes: 16 additions & 0 deletions kbcstorage/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ def list(self, component_id):
url = '{}/{}/configs'.format(self.base_url, component_id)
return self._get(url)

def list_config_workspaces(self, component_id, config_id):
"""
Lists workspaces for component configuration.

Args:
component_id (str): The id of the component.
config_id (str): The id of the configuration.

Raises:
requests.HTTPError: If the API request fails.
"""
if not isinstance(component_id, str) or component_id == '':
raise ValueError("Invalid component_id '{}'.".format(component_id))
url = f'{self.base_url}/{component_id}/configs/{config_id}/workspaces'
return self._get(url)

def create(self, component_id, name, description='', configuration=None, state=None, change_description='',
is_disabled=False, configuration_id=None):
"""
Expand Down
47 changes: 36 additions & 11 deletions kbcstorage/workspaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
from kbcstorage.base import Endpoint
from kbcstorage.files import Files
from kbcstorage.jobs import Jobs
from typing import List # the legacy Workspaces class below unfortunately defines its own method called list


def _make_body(mapping, source_key='source'):
def _make_body(mapping, source_key='source', preserve: bool = True):
"""
Given a dict mapping Keboola tables to aliases, construct the body of
the HTTP request to load said tables.
Expand All @@ -21,7 +22,7 @@ def _make_body(mapping, source_key='source'):
be loaded (ie. 'in.c-bucker.table_name') and values contain the
aliases to which they will be loaded (ie. 'table_name').
"""
body = {}
body = {'preserve': str(preserve).lower()}
template = 'input[{0}][{1}]'
for i, (k, v) in enumerate(mapping.items()):
body[template.format(i, source_key)] = k
Expand Down Expand Up @@ -72,7 +73,7 @@ def detail(self, workspace_id):
url = '{}/{}'.format(self.base_url, workspace_id)
return self._get(url)

def create(self, backend=None, timeout=None):
def create(self, backend=None, timeout=None, login_type=None, public_key=None, read_all_objects=False):
"""
Create a new Workspace and return the credentials.

Expand All @@ -87,7 +88,10 @@ def create(self, backend=None, timeout=None):
"""
body = {
'backend': backend,
'statementTimeoutSeconds': timeout
'statementTimeoutSeconds': timeout,
'loginType': login_type,
'publicKey': public_key,
'readOnlyStorageAccess': str(read_all_objects).lower() # convert bool to lowercase true or false
}

return self._post(self.base_url, data=body)
Expand Down Expand Up @@ -122,29 +126,50 @@ def reset_password(self, workspace_id):
url = '{}/{}/password'.format(self.base_url, workspace_id)
return self._post(url)

def load_tables(self, workspace_id, table_mapping, preserve=None):
def set_public_key(self, workspace_id, public_key):
"""
Set the public key for the workspace.
"""
data = {
'publicKey': public_key
}
url = '{}/{}/public-key'.format(self.base_url, workspace_id)
return self._post(url, json=data)

def load_tables(self, workspace_id: int | str, table_mapping: dict | List[dict], preserve=True, load_type='load'):
"""
Load tabes from storage into a workspace.

Args:
workspace_id (int or str): The id of the workspace to which to load
the tables.
table_mapping (:obj:`dict`): Source table names mapped to
destination table names.
table_mapping (:obj:`dict` or :obj:`list`): Source table names mapped to
destination table names. or a list of dicts with detailed tables specification.
preserve (bool): If False, drop tables, else keep tables in
workspace.
load_type (str): Type of load, either 'load' or 'load-clone'. Defaults to 'load'.

Raises:
requests.HTTPError: If the API request fails.

Todo:
* Column data types.
"""
body = _make_body(table_mapping)
body['preserve'] = preserve
url = '{}/{}/load'.format(self.base_url, workspace_id)
load_type = load_type.lower()
if load_type not in ['load', 'load-clone']:
raise ValueError("Invalid load_type: {}, supports only load and load-clone".format(load_type))

url = "/".join([self.base_url, str(workspace_id), load_type])

req = None
if isinstance(table_mapping, dict):
body = _make_body(table_mapping, preserve=preserve)
req = self._post(url, data=body)
elif isinstance(table_mapping, list):
body = {'input': table_mapping, 'preserve': str(preserve).lower()}
req = self._post(url, json=body)

return self._post(url, data=body)
return req

def load_files(self, workspace_id, file_mapping):
"""
Expand Down
Loading