Skip to content

Client WebApp API #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
26 changes: 26 additions & 0 deletions dataikuapi/dss/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .discussion import DSSObjectDiscussions
from .ml import DSSMLTask
from .analysis import DSSAnalysis
from .webapp import DSSWebApp, DSSWebAppHead
from dataikuapi.utils import DataikuException


Expand Down Expand Up @@ -823,6 +824,31 @@ def get_macro(self, runnable_type):
"""
return DSSMacro(self.client, self.project_key, runnable_type)

########################################################
# Webapps
########################################################

def list_webapps(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopt the newer standard of returning either listitem or object. See list_scenarios for an up-to-date example. This allows basic listing with a single API call instead of N+1

Provide properties on the core things in the DSSWebAppListItem

"""
List the webapps heads of this project

:returns: the list of the webapps as :class:`dataikuapi.dss.webapp.DSSWebAppHead`
"""
webapps = self.client._perform_json(
"GET", "/projects/%s/webapps/" % self.project_key)
return [DSSWebAppHead(self.client, self.project_key, w["id"], w) for w in webapps]

def get_webapp(self, webapp_id):
"""
Get a handle to interact with a specific webapp

:param webapp_id: the identifier of a webapp
:returns: A :class:`dataikuapi.dss.macro.DSSWebApp` webapp handle
"""
definition = self.client._perform_json(
"GET", "/projects/%s/webapps/%s" % (self.project_key, webapp_id))
return DSSWebApp(self.client, self.project_key, webapp_id, definition)

########################################################
# Wiki
########################################################
Expand Down
67 changes: 67 additions & 0 deletions dataikuapi/dss/webapp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import sys

if sys.version_info >= (3,0):
import urllib.parse
dku_quote_fn = urllib.parse.quote
else:
import urllib
dku_quote_fn = urllib.quote

class DSSWebApp(object):
"""
A handle to manage a webapp
"""
def __init__(self, client, project_key, webapp_id, definition):
"""Do not call directly, use :meth:`dataikuapi.dss.project.DSSProject.get_webapps`"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

self.client = client
self.project_key = project_key
self.webapp_id = webapp_id
self.definition = definition

"""
Update an existing webapp

:returns: a webapp state excerpt
:rtype: :class:`dataikuapi.dss.webapp.DSSWebAppSaveResponse`
"""
def update(self):
response = self.client._perform_json("PUT", "/projects/%s/webapps/%s" % (self.project_key, self.webapp_id), body=self.definition)
return DSSWebAppSaveResponse(self.client, self.project_key, self.webapp_id, response)

"""
Stop a webapp
"""
def stop_backend(self):
self.client._perform_empty("PUT", "/projects/%s/webapps/%s/stop-backend" % (self.project_key, self.webapp_id))
return

"""
Restart a webapp
"""
def restart_backend(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this corresponds to what the API really does, the fact that there is a "restart" method but no "start" method could be confusing.

Not sure what the best to do is here. Maybe call the method start_or_restart_backend

self.client._perform_empty("PUT", "/projects/%s/webapps/%s/restart-backend" % (self.project_key, self.webapp_id))
return


class DSSWebAppSaveResponse(object):
"""
Response for the update method on a WebApp
"""
def __init__(self, client, project_key, webapp_id, definition):
"""Do not call directly, use :meth:`dataikuapi.dss.webapp.DSSWebApp.update`"""
self.client = client
self.project_key = project_key
self.webapp_id = webapp_id
self.definition = definition


class DSSWebAppHead(object):
"""
A handle to manage a WebApp head
"""
def __init__(self, client, project_key, webapp_id, definition):
"""Do not call directly, use :meth:`dataikuapi.dss.project.DSSProject.get_webapps`"""
self.client = client
self.project_key = project_key
self.webapp_id = webapp_id
self.definition = definition
12 changes: 6 additions & 6 deletions tests/user_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ def list_users_test():

def create_delete_user_test():
client = DSSClient(host, apiKey)
count = len(client.list_users())
count = len(client.list_users())

user = client.create_user("toto", "password", "display name of toto", groups=['a','b'])
eq_(count + 1, len(client.list_users()))

user.delete()
eq_(count, len(client.list_users()))

def get_set_user_test():
client = DSSClient(host, apiKey)
user = client.create_user("toto", "password", "display name of toto", groups=['a','b'])

desc = user.get_definition()
desc['displayName'] = 'tata'
user.set_definition(desc)
desc2 = user.get_definition()

eq_('tata', desc2['displayName'])

user.delete()
Expand Down
63 changes: 63 additions & 0 deletions tests/webapps_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from time import sleep
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove this test class as it cannot be run automatically

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talk with @Basharsh96 first :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a copy of the test and I'll add it later to the tests in the CI pipeline I'm working on. Thank you, you can safely remove it 😊

from dataikuapi.dssclient import DSSClient
from dataikuapi.dss.project import DSSProject
from nose.tools import ok_
from nose.tools import eq_

host="http://localhost:8083"
apiKey="CMZBjFkUgcDh08S3awoPyVIweBelxPjy"
testProjectKey="WEBAPPS"
testWebAppPythonId="VCMN2ra"

def remove_key(d, key):
r = dict(d)
del r[key]
return r

class webapp_api_tests(object):

def setUp(self):
self.client = DSSClient(host, apiKey)
self.project = DSSProject(self.client, testProjectKey)

def list_webapps_test(self):
webapps = self.project.list_webapps();
ok_(len(webapps) > 0)


def get_python_webapp_test(self):
webapp = self.project.get_webapp(testWebAppPythonId)
ok_(webapp is not None)

def update_python_webapp_test(self):
webapp_pre = self.project.get_webapp(testWebAppPythonId)
webapp_pre.update()
webapp_post = self.project.get_webapp(testWebAppPythonId)
eq_(webapp_pre.project_key, webapp_post.project_key)
eq_(webapp_pre.webapp_id, webapp_post.webapp_id)
eq_(remove_key(webapp_pre.definition, "versionTag"), remove_key(webapp_post.definition, "versionTag"))
eq_(webapp_pre.definition["versionTag"]["versionNumber"]+1,webapp_post.definition["versionTag"]["versionNumber"])

def restart_backend_test(self):
"""
WARNING: you should manually stop the backend before this test
"""
filtered_webapps = [w for w in self.project.list_webapps() if w.webapp_id == testWebAppPythonId]
webapp = self.project.get_webapp(testWebAppPythonId)
ok_(not filtered_webapps[0].definition["backendRunning"],"The backend should be stopped before the test")
webapp.restart_backend()
sleep(2)
filtered_webapps = [w for w in self.project.list_webapps() if w.webapp_id == testWebAppPythonId]
ok_(filtered_webapps[0].definition["backendRunning"])

def stop_backend_test(self):
"""
WARNING: you should manually start the backend before this test
"""
filtered_webapps = [w for w in self.project.list_webapps() if w.webapp_id == testWebAppPythonId]
webapp = self.project.get_webapp(testWebAppPythonId)
ok_(filtered_webapps[0].definition["backendRunning"],"The backend should be started before the test")
webapp.stop_backend()
sleep(2)
filtered_webapps = [w for w in self.project.list_webapps() if w.webapp_id == testWebAppPythonId]
ok_(not filtered_webapps[0].definition["backendRunning"])