Skip to content

Commit dc04057

Browse files
authored
Merge pull request #232 from dataiku/task/public-api-for-kubikles
Task/public api for kubikles
2 parents 8976d20 + eb6c0e1 commit dc04057

File tree

4 files changed

+338
-2
lines changed

4 files changed

+338
-2
lines changed

dataikuapi/dss/admin.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .future import DSSFuture
44
import json, warnings
5+
from datetime import datetime
56

67

78
class DSSConnectionInfo(dict):
@@ -1494,3 +1495,114 @@ def total_scenarios_count(self):
14941495
@property
14951496
def total_active_with_trigger_scenarios_count(self):
14961497
return self.data["scenarios"]["activeWithTriggers"]
1498+
1499+
1500+
class DSSCodeStudioTemplateListItem(object):
1501+
"""An item in a list of code studio templates. Do not instantiate this class, use :meth:`dataikuapi.DSSClient.list_code_studio_templates`"""
1502+
def __init__(self, client, data):
1503+
self.client = client
1504+
self._data = data
1505+
1506+
def to_code_studio_template(self):
1507+
"""Gets the :class:`DSSCodeStudioTemplate` corresponding to this code studio template """
1508+
return DSSCodeStudioTemplate(self.client, self._data["id"])
1509+
1510+
@property
1511+
def name(self):
1512+
return self._data["name"]
1513+
@property
1514+
def id(self):
1515+
return self._data["id"]
1516+
@property
1517+
def build_for_configs(self):
1518+
return self._data.get("buildFor", [])
1519+
@property
1520+
def last_built(self):
1521+
ts = self._data.get("lastBuilt", 0)
1522+
if ts > 0:
1523+
return datetime.fromtimestamp(ts / 1000)
1524+
else:
1525+
return None
1526+
1527+
class DSSCodeStudioTemplate(object):
1528+
"""
1529+
A handle to interact with a code studio template on the DSS instance
1530+
"""
1531+
def __init__(self, client, template_id):
1532+
"""Do not call that directly, use :meth:`dataikuapi.DSSClient.get_code_studio_template`"""
1533+
self.client = client
1534+
self.template_id = template_id
1535+
1536+
########################################################
1537+
# Template description
1538+
########################################################
1539+
1540+
def get_settings(self):
1541+
"""
1542+
Get the template's settings.
1543+
1544+
:returns: a :class:`DSSCodeStudioTemplateSettings` object to interact with code studio template settings
1545+
:rtype: :class:`DSSCodeStudioTemplateSettings`
1546+
"""
1547+
settings = self.client._perform_json("GET", "/admin/code-studios/%s" % (self.template_id))
1548+
return DSSCodeStudioTemplateSettings(self.client, self.template_id, settings)
1549+
1550+
########################################################
1551+
# Building
1552+
########################################################
1553+
1554+
def build(self):
1555+
"""
1556+
Build or rebuild the template.
1557+
1558+
:returns: a :class:`~dataikuapi.dss.future.DSSFuture` handle to the task of building the image
1559+
"""
1560+
future_response = self.client._perform_json("POST", "/admin/code-studios/%s/build" % (self.template_id))
1561+
return DSSFuture(self.client, future_response.get('jobId', None), future_response)
1562+
1563+
class DSSCodeStudioTemplateSettings(object):
1564+
"""
1565+
The settings of a code studio template
1566+
"""
1567+
def __init__(self, client, template_id, settings):
1568+
"""Do not call directly, use :meth:`DSSCodeStudioTemplate.get_settings`"""
1569+
self.client = client
1570+
self.template_id = template_id
1571+
self.settings = settings
1572+
1573+
def get_raw(self):
1574+
"""
1575+
Gets all settings as a raw dictionary. This returns a reference to the raw settings, not a copy,
1576+
"""
1577+
return self.settings
1578+
1579+
def get_built_for_all_container_confs(self):
1580+
"""
1581+
Return whether the template an image for each container config
1582+
"""
1583+
return self.settings.get("allContainerConfs", False)
1584+
1585+
def get_built_container_confs(self):
1586+
"""
1587+
Return the list of container configs for which the template builds an image (if not all)
1588+
"""
1589+
return self.settings.get("containerConfs", [])
1590+
1591+
def set_built_container_confs(self, *configs, **kwargs):
1592+
"""
1593+
Set the list of container configs for which the template builds an image
1594+
1595+
:param boolean all: if True, an image is built for each config
1596+
:param list configs: list of configuration names to build images for
1597+
"""
1598+
all = kwargs.get("all", False)
1599+
self.settings['allContainerConfs'] = all
1600+
if not all:
1601+
self.settings['containerConfs'] = configs
1602+
1603+
def save(self):
1604+
"""
1605+
Saves the settings of the code studio template
1606+
"""
1607+
self.client._perform_empty("PUT", "/admin/code-studios/%s" % (self.template_id), body=self.settings)
1608+

dataikuapi/dss/codestudio.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
from ..utils import DataikuException
2+
import json
3+
from datetime import datetime
4+
from .future import DSSFuture
5+
6+
class DSSCodeStudioObjectListItem(object):
7+
"""An item in a list of code studios. Do not instantiate this class, use :meth:`dataikuapi.dss.project.DSSProject.list_code_studios`"""
8+
def __init__(self, client, project_key, data):
9+
self.client = client
10+
self.project_key = project_key
11+
self._data = data
12+
13+
def to_code_studio(self):
14+
"""Gets the :class:`DSSCodeStudioObject` corresponding to this code studio object """
15+
return DSSCodeStudioObject(self.client, self.project_key, self._data["id"])
16+
17+
@property
18+
def name(self):
19+
return self._data["name"]
20+
@property
21+
def id(self):
22+
return self._data["id"]
23+
@property
24+
def owner(self):
25+
return self._data["owner"]
26+
@property
27+
def template_id(self):
28+
return self._data["templateId"]
29+
@property
30+
def template_label(self):
31+
return self._data.get('desc', {}).get('label', self._data['id'])
32+
@property
33+
def template_description(self):
34+
return self._data.get('desc', {}).get('shortDesc', '')
35+
36+
37+
class DSSCodeStudioObject(object):
38+
"""
39+
A handle to manage a code studio object of a project
40+
"""
41+
def __init__(self, client, project_key, code_studio_id):
42+
"""Do not call directly, use :meth:`dataikuapi.dss.project.DSSProject.get_code_studio`"""
43+
self.client = client
44+
self.project_key = project_key
45+
self.code_studio_id = code_studio_id
46+
47+
def delete(self):
48+
"""
49+
Delete the code studio
50+
"""
51+
self.client._perform_empty("DELETE", "/projects/%s/code-studios/%s" % (self.project_key, self.code_studio_id))
52+
53+
def get_settings(self):
54+
"""
55+
Get the code studio object's definition
56+
57+
:returns: a handle to manage the code studio definition
58+
:rtype: :class:`dataikuapi.dss.codestudio.DSSCodeStudioObjectSettings`
59+
"""
60+
settings = self.client._perform_json("GET", "/projects/%s/code-studios/%s" % (self.project_key, self.code_studio_id))
61+
return DSSCodeStudioObjectSettings(self.client, self.project_key, self.code_studio_id, settings)
62+
63+
def get_status(self):
64+
"""
65+
Get the code studio object's state
66+
67+
:returns: a handle to inspect the code studio state
68+
:rtype: :class:`dataikuapi.dss.codestudio.DSSCodeStudioObjectStatus`
69+
"""
70+
status = self.client._perform_json("GET", "/projects/%s/code-studios/%s/status" % (self.project_key, self.code_studio_id))
71+
return DSSCodeStudioObjectStatus(self.client, self.project_key, self.code_studio_id, status)
72+
73+
def stop(self):
74+
"""
75+
Stop a running code studio
76+
77+
:returns: a future to wait on the stop, or None if already stopped
78+
:rtype: :class:`dataikuapi.dss.future.DSSFuture`
79+
"""
80+
ret = self.client._perform_json("POST", "/projects/%s/code-studios/%s/stop" % (self.project_key, self.code_studio_id))
81+
return DSSFuture.from_resp(self.client, ret)
82+
83+
def restart(self):
84+
"""
85+
Restart a code studio
86+
87+
:returns: a future to wait on the start
88+
:rtype: :class:`dataikuapi.dss.future.DSSFuture`
89+
"""
90+
ret = self.client._perform_json("POST", "/projects/%s/code-studios/%s/restart" % (self.project_key, self.code_studio_id))
91+
return DSSFuture.from_resp(self.client, ret)
92+
93+
class DSSCodeStudioObjectSettings(object):
94+
"""
95+
Settings for the code studio object
96+
"""
97+
def __init__(self, client, project_key, code_studio_id, settings):
98+
"""Do not call directly, use :meth:`dataikuapi.dss.codestudio.DSSCodeStudioObject.get_settings`"""
99+
self.client = client
100+
self.project_key = project_key
101+
self.code_studio_id = code_studio_id
102+
self.settings = settings
103+
104+
def get_raw(self):
105+
"""
106+
Gets all settings as a raw dictionary. This returns a reference to the raw settings, not a copy,
107+
"""
108+
return self.settings
109+
110+
@property
111+
def template_id(self):
112+
return self.settings["templateId"]
113+
@property
114+
def lib_name(self):
115+
return self.settings["libName"]
116+
117+
118+
class DSSCodeStudioObjectStatus(object):
119+
"""
120+
Status of a code studio object
121+
"""
122+
def __init__(self, client, project_key, code_studio_id, status):
123+
"""Do not call directly, use :meth:`dataikuapi.dss.codestudio.DSSCodeStudioObject.get_state`"""
124+
self.client = client
125+
self.project_key = project_key
126+
self.code_studio_id = code_studio_id
127+
self.status = status
128+
129+
def get_raw(self):
130+
"""
131+
Gets the status as a raw dictionary. This returns a reference to the raw status, not a copy,
132+
"""
133+
return self.status
134+
135+
@property
136+
def state(self):
137+
return self.status["state"]
138+
@property
139+
def last_state_change(self):
140+
ts = self.status.get("lastStateChange", 0)
141+
if ts > 0:
142+
return datetime.fromtimestamp(ts / 1000)
143+
else:
144+
return None

dataikuapi/dss/project.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from .analysis import DSSAnalysis
2626
from .flow import DSSProjectFlow
2727
from .app import DSSAppManifest
28-
28+
from .codestudio import DSSCodeStudioObject, DSSCodeStudioObjectListItem
2929

3030
class DSSProject(object):
3131
"""
@@ -1606,6 +1606,7 @@ def get_app_manifest(self):
16061606
raw_data = self.client._perform_json("GET", "/projects/%s/app-manifest" % self.project_key)
16071607
return DSSAppManifest(self.client, raw_data, self.project_key)
16081608

1609+
########################################################
16091610
# MLflow experiment tracking
16101611
########################################################
16111612
def setup_mlflow(self, managed_folder, host=None):
@@ -1628,6 +1629,55 @@ def get_mlflow_extension(self):
16281629
"""
16291630
return DSSMLflowExtension(client=self.client, project_key=self.project_key)
16301631

1632+
1633+
1634+
########################################################
1635+
# Code studios
1636+
########################################################
1637+
def list_code_studios(self, as_type="listitems"):
1638+
"""
1639+
List the code studio objects in this project
1640+
1641+
:returns: the list of the code studio objects, each one as a JSON object
1642+
"""
1643+
items = self.client._perform_json(
1644+
"GET", "/projects/%s/code-studios/" % self.project_key)
1645+
if as_type == "listitems" or as_type == "listitem":
1646+
return [DSSCodeStudioObjectListItem(self.client, self.project_key, item) for item in items]
1647+
elif as_type == "objects" or as_type == "object":
1648+
return [DSSCodeStudioObject(self.client, self.project_key, item["id"]) for item in items]
1649+
else:
1650+
raise ValueError("Unknown as_type")
1651+
1652+
def get_code_studio(self, code_studio_id):
1653+
"""
1654+
Get a handle to interact with a specific code studio object
1655+
1656+
:param str code_studio_id: the identifier of the desired code studio object
1657+
1658+
:returns: A :class:`dataikuapi.dss.codestudio.DSSCodeStudioObject` code studio object handle
1659+
"""
1660+
return DSSCodeStudioObject(self.client, self.project_key, code_studio_id)
1661+
1662+
def create_code_studio(self, name, template_id):
1663+
"""
1664+
Create a new code studio object in the project, and return a handle to interact with it
1665+
1666+
:param str name: the name of the code studio object
1667+
:param str template_id: the identifier of a code studio template
1668+
1669+
:returns: A :class:`dataikuapi.dss.codestudio.DSSCodeStudioObject` code studio object handle
1670+
"""
1671+
obj = {
1672+
"name" : name,
1673+
"templateId" : template_id
1674+
}
1675+
res = self.client._perform_json("POST", "/projects/%s/code-studios/" % self.project_key, body = obj)
1676+
code_studio_id = res['codeStudio']['id']
1677+
return DSSCodeStudioObject(self.client, self.project_key, code_studio_id)
1678+
1679+
1680+
16311681
class TablesImportDefinition(object):
16321682
"""
16331683
Temporary structure holding the list of tables to import

dataikuapi/dssclient.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .dss.project import DSSProject
1212
from .dss.app import DSSApp
1313
from .dss.plugin import DSSPlugin
14-
from .dss.admin import DSSPersonalApiKeyListItem, DSSUser, DSSUserActivity, DSSOwnUser, DSSGroup, DSSConnection, DSSGeneralSettings, DSSCodeEnv, DSSGlobalApiKey, DSSCluster, DSSGlobalUsageSummary, DSSInstanceVariables, DSSPersonalApiKey
14+
from .dss.admin import DSSPersonalApiKeyListItem, DSSUser, DSSUserActivity, DSSOwnUser, DSSGroup, DSSConnection, DSSGeneralSettings, DSSCodeEnv, DSSGlobalApiKey, DSSCluster, DSSCodeStudioTemplate, DSSCodeStudioTemplateListItem, DSSGlobalUsageSummary, DSSInstanceVariables, DSSPersonalApiKey
1515

1616
from .dss.meaning import DSSMeaning
1717
from .dss.sqlquery import DSSSQLQuery
@@ -618,6 +618,36 @@ def create_cluster(self, cluster_name, cluster_type='manual', params=None, clust
618618
raise Exception('Cluster creation failed : %s' % (json.dumps(resp.get('messages', {}).get('messages', {}))))
619619
return DSSCluster(self, resp['id'])
620620

621+
622+
########################################################
623+
# Code studio templates
624+
########################################################
625+
626+
def list_code_studio_templates(self, as_type='listitems'):
627+
"""
628+
List all code studio templates on the DSS instance
629+
630+
:returns: List of templates (name, type)
631+
"""
632+
items = self._perform_json("GET", "/admin/code-studios/")
633+
if as_type == "listitems" or as_type == "listitem":
634+
return [DSSCodeStudioTemplateListItem(self, item) for item in items]
635+
elif as_type == "objects" or as_type == "object":
636+
return [DSSCodeStudioTemplate(self, item["id"]) for item in items]
637+
else:
638+
raise ValueError("Unknown as_type")
639+
640+
def get_code_studio_template(self, template_id):
641+
"""
642+
Get a handle to interact with a specific code studio template
643+
644+
:param str template_id: the template id of the desired code studio template
645+
646+
:returns: A :class:`dataikuapi.dss.admin.DSSCodeStudioTemplate` code studio template handle
647+
"""
648+
return DSSCodeStudioTemplate(self, template_id)
649+
650+
621651
########################################################
622652
# Global API Keys
623653
########################################################

0 commit comments

Comments
 (0)