Skip to content

Commit d3e2455

Browse files
authored
Merge PR #81 Plugin uninstall
from perso/lpenet/plugin-uninstall
2 parents 47a1bbb + fa3d551 commit d3e2455

File tree

1 file changed

+123
-9
lines changed

1 file changed

+123
-9
lines changed

dataikuapi/dss/plugin.py

Lines changed: 123 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
from .dataset import DSSDataset
2-
from .recipe import DSSRecipe
3-
from .managedfolder import DSSManagedFolder
4-
from .savedmodel import DSSSavedModel
5-
from .job import DSSJob
6-
from .scenario import DSSScenario
7-
from .apiservice import DSSAPIService
8-
import sys
1+
from dataikuapi.utils import DataikuException
2+
93

104
class DSSPluginSettings(object):
115
"""
@@ -30,6 +24,7 @@ def save(self):
3024
"""Saves the settings to DSS"""
3125
self.client._perform_empty("POST", "/plugins/%s/settings" % (self.plugin_id), body=self.settings)
3226

27+
3328
class DSSPlugin(object):
3429
"""
3530
A plugin on the DSS instance
@@ -116,6 +111,41 @@ def update_from_git(self, repository_url, checkout = "master", subpath=None):
116111
})
117112
return self.client.get_future(ret["jobId"])
118113

114+
########################################################
115+
# Plugin uninstall/delete
116+
########################################################
117+
118+
def list_usages(self, project_key=None):
119+
"""
120+
Get the list of usages of the plugin.
121+
122+
:param str project_key: optional key of project where to look for usages. Default is None and looking in all projects.
123+
:return: a :class:`DSSPluginUsages`
124+
"""
125+
return DSSPluginUsages(
126+
self.client._perform_json("GET", "/plugins/{pluginId}/actions/listUsages".format(pluginId=self.plugin_id),
127+
params={"projectKey": project_key})
128+
)
129+
130+
def delete(self, force=False):
131+
"""
132+
Delete a plugin.
133+
134+
If not forced (default), pre-deletion checks will be run (as by :func:`prepare_delete` and the deletion will be
135+
performed if and only if no usage of the plugin is detected and no error occurred during usages analysis.
136+
137+
:param bool force: if True, plugin will be deleted even if usages are found or errors occurred during usages
138+
analysis. Default is False.
139+
:return: a :class:`dataikuapi.dssfuture.DSSFuture`
140+
"""
141+
142+
params = {
143+
"force": force
144+
}
145+
ret = self.client._perform_json("POST", "/plugins/{pluginId}/actions/delete".format(pluginId=self.plugin_id),
146+
body=params)
147+
return self.client.get_future(ret.get("jobId", None))
148+
119149
########################################################
120150
# Managing the dev plugin's contents
121151
########################################################
@@ -147,4 +177,88 @@ def put_file(self, path, f):
147177
data = f.read() # eat it all, because making it work with a path variable and a MultifilePart in swing looks complicated
148178
return self.client._perform_empty("POST", "/plugins/%s/contents/%s" % (self.plugin_id, path), raw_body=data)
149179

150-
180+
181+
class DSSPluginUsage(object):
182+
"""
183+
Information on a usage of an element of a plugin.
184+
185+
Has the following properties:
186+
- element_kind: webapps, python-formats,...
187+
- element_type: type name of the element
188+
- object_id: id of the object using the plugin element. Can be None.
189+
- object_type: type of the object using the plugin element. Can be None.
190+
- project_key: project key of the object using the plugin element. Can be None.
191+
"""
192+
def __init__(self, data):
193+
"""
194+
Instantiate a DSSPluginUsage from the dict of its properties.
195+
:param dict data: dict of properties
196+
"""
197+
self.element_kind = data["elementKind"]
198+
self.element_type = data["elementType"]
199+
self.object_id = data.get("objectId", None)
200+
self.object_type = data.get("objectType", None)
201+
self.project_key = data.get("projectKey", None)
202+
203+
204+
class DSSMissingType(object):
205+
"""
206+
Information on a type not found while analyzing usages of a plugin.
207+
208+
Has the following properties:
209+
- missing type: the missing type
210+
- object_id: id of the object depending on the missing type. Can be None.
211+
- object_type: type of the object depending on the missing type. Can be None.
212+
- project_key: project key of the object depending on the missing type. Can be None.
213+
"""
214+
def __init__(self, data):
215+
"""
216+
Instantiate a DSSMissingType from the dict of its properties
217+
:param dict data: dictionary of properties
218+
"""
219+
self.missing_type = data["missingType"]
220+
self.object_id = data.get("objectId", None)
221+
self.object_type = data.get("objectType", None)
222+
self.project_key = data.get("projectKey", None)
223+
224+
225+
class DSSPluginUsages(object):
226+
"""
227+
Information on the usages of a plugin.
228+
229+
Has the following properties:
230+
- usages (list of :class:`DSSPluginUsage`)
231+
- missing_types (a list of :class:`DSSMissingType`).
232+
233+
Some custom types may not be found during usage analysis, typically when a plugin was removed
234+
but is still used. This prevents some detailed analysis and may hide some uses.
235+
This information is provided in missing_types.
236+
"""
237+
def __init__(self, data):
238+
"""
239+
Initialize a DSSPluginUsages from a dict of its properties
240+
241+
:param dict data: the usages as json dict
242+
"""
243+
self._data = data
244+
self.usages = []
245+
self.missing_types = []
246+
for json_usage in data.get("usages", []):
247+
self.usages.append(DSSPluginUsage(json_usage))
248+
for json_missing_type in data.get("missingTypes"):
249+
self.missing_types.append(DSSMissingType(json_missing_type))
250+
251+
def get_raw(self):
252+
"""
253+
Get plugin usages as a dictionary.
254+
:rtype: dict
255+
"""
256+
return self._data
257+
258+
def maybe_used(self):
259+
"""
260+
Returns true if the plugin maybe in use, as usages of the plugin were found, or errors
261+
encountered during analysis.
262+
:return:
263+
"""
264+
return not (not self.usages and not self.missing_types)

0 commit comments

Comments
 (0)