diff --git a/dataikuapi/dss/apideployer.py b/dataikuapi/dss/apideployer.py index 339ae2bf..5f96c7b7 100644 --- a/dataikuapi/dss/apideployer.py +++ b/dataikuapi/dss/apideployer.py @@ -1,6 +1,6 @@ import json from .future import DSSFuture - +from ..utils import CallableStr class DSSAPIDeployer(object): """ @@ -60,7 +60,7 @@ def list_stages(self): """ Lists infrastructure stages of the API Deployer - :rtype: a list of dict. Each dict contains a field "id" for the stage identifier and "desc" for its description. + :rtype: list of dict. Each dict contains a field "id" for the stage identifier and "desc" for its description. :rtype: list """ return self.client._perform_json("GET", "/api-deployer/stages") @@ -152,7 +152,7 @@ def get_service(self, service_id): class DSSAPIDeployerInfra(object): """ - A Deployment infrastructure on the API Deployer + An API Deployer infrastructure. Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployer.get_infra` """ @@ -160,8 +160,19 @@ def __init__(self, client, infra_id): self.client = client self.infra_id = infra_id + @property def id(self): - return self.infra_id + return CallableStr(self.infra_id) + + def get_status(self): + """ + Returns status information about this infrastructure + + :rtype: :class:`dataikuapi.dss.apideployer.DSSAPIDeployerInfraStatus` + """ + light = self.client._perform_json("GET", "/api-deployer/infras/%s" % (self.infra_id)) + + return DSSAPIDeployerInfraStatus(self.client, self.infra_id, light) def get_settings(self): """ @@ -186,7 +197,8 @@ def delete(self): class DSSAPIDeployerInfraSettings(object): - """The settings of an API Deployer Infra. + """ + The settings of an API Deployer infrastructure Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerInfra.get_settings` """ @@ -238,6 +250,35 @@ def save(self): body = self.settings) +class DSSAPIDeployerInfraStatus(object): + """ + The status of an API Deployer infrastructure. + + Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerInfra.get_status` + """ + def __init__(self, client, infra_id, light_status): + self.client = client + self.infra_id = infra_id + self.light_status = light_status + + def get_deployments(self): + """ + Returns the deployments that are deployed on this infrastructure + + :returns: a list of deployments + :rtype: list of :class:`dataikuapi.dss.apideployer.DSSAPIDeployerDeployment` + """ + return [DSSAPIDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"]] + + def get_raw(self): + """ + Gets the raw status information. This returns a dictionary with various information about the infrastructure + + :rtype: dict + """ + return self.light_status + + ############################################### # Deployments ############################################### @@ -252,11 +293,13 @@ def __init__(self, client, deployment_id): self.client = client self.deployment_id = deployment_id + @property def id(self): - return self.deployment_id + return CallableStr(self.deployment_id) def get_status(self): - """Returns status information about this deployment + """ + Returns status information about this deployment :rtype: dataikuapi.dss.apideployer.DSSAPIDeployerDeploymentStatus """ @@ -302,7 +345,8 @@ def delete(self): class DSSAPIDeployerDeploymentSettings(object): - """The settings of an API Deployer deployment. + """ + The settings of an API Deployer deployment. Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerDeployment.get_settings` """ @@ -321,7 +365,9 @@ def get_raw(self): return self.settings def set_enabled(self, enabled): - """Enables or disables this deployment""" + """ + Enables or disables this deployment + """ self.settings["enabled"] = enabled def set_single_version(self, version): @@ -336,14 +382,17 @@ def set_single_version(self, version): } def save(self): - """Saves back these settings to the deployment""" + """ + Saves back these settings to the deployment + """ self.client._perform_empty( "PUT", "/api-deployer/deployments/%s/settings" % (self.deployment_id), body = self.settings) class DSSAPIDeployerDeploymentStatus(object): - """The status of an API Deployer deployment. + """ + The status of an API Deployer deployment. Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerDeployment.get_status` """ @@ -365,12 +414,15 @@ def get_light(self): def get_heavy(self): """ Gets the 'heavy' (full) status. This returns a dictionary with various information about the deployment + :rtype: dict """ return self.heavy_status def get_service_urls(self): - """Returns service-level URLs for this deployment (ie without the enpdoint-specific suffix)""" + """ + Returns service-level URLs for this deployment (ie without the enpdoint-specific suffix) + """ if "deployedServiceId" in self.light_status["deploymentBasicInfo"]: service_id = self.light_status["deploymentBasicInfo"]["deployedServiceId"] @@ -385,7 +437,8 @@ def get_service_urls(self): raise ValueError("PublicURL not available for this deployment. It might still be initializing") def get_health(self): - """Returns the health of this deployment as a string + """ + Returns the health of this deployment as a string :returns: HEALTHY if the deployment is working properly, various other status otherwise :rtype: string @@ -411,8 +464,9 @@ def __init__(self, client, service_id): self.client = client self.service_id = service_id + @property def id(self): - return self.service_id + return CallableStr(self.service_id) def get_status(self): """ @@ -452,6 +506,7 @@ def get_settings(self): def delete_version(self, version): """ Deletes a version from this service + :param string version: The version to delete """ self.client._perform_empty( @@ -468,7 +523,8 @@ def delete(self): class DSSAPIDeployerServiceSettings(object): - """The settings of an API Deployer Service. + """ + The settings of an API Deployer Service. Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerService.get_settings` """ @@ -487,14 +543,17 @@ def get_raw(self): return self.settings def save(self): - """Saves back these settings to the API service""" + """ + Saves back these settings to the API service + """ self.client._perform_empty( "PUT", "/api-deployer/services/%s/settings" % (self.service_id), body = self.settings) class DSSAPIDeployerServiceStatus(object): - """The status of an API Deployer Service. + """ + The status of an API Deployer Service. Do not create this directly, use :meth:`~dataikuapi.dss.apideployer.DSSAPIDeployerService.get_status` """ @@ -503,6 +562,20 @@ def __init__(self, client, service_id, light_status): self.service_id = service_id self.light_status = light_status + def get_deployments(self, infra_id=None): + """ + Returns the deployments that have been created from this published project + + :param str infra_id: Identifier of an infra, allows to only keep in the returned list the deployments on this infra. + If not set, the list contains all the deployments using this published project, across every infra of the Project Deployer. + + :returns: a list of deployments + :rtype: list of :class:`dataikuapi.dss.apideployer.DSSAPIDeployerDeployment` + """ + if infra_id is None: + return [DSSAPIDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"]] + return [DSSAPIDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"] if infra_id == deployment["infraId"]] + def get_versions(self): """ Returns the versions of this service that have been published on the API Service @@ -517,6 +590,7 @@ def get_versions(self): def get_raw(self): """ Gets the raw status information. This returns a dictionary with various information about the service, + :rtype: dict """ return self.light_status diff --git a/dataikuapi/dss/project.py b/dataikuapi/dss/project.py index 6557e8b6..4831936d 100644 --- a/dataikuapi/dss/project.py +++ b/dataikuapi/dss/project.py @@ -936,7 +936,7 @@ def get_api_service(self, service_id): return DSSAPIService(self.client, self.project_key, service_id) ######################################################## - # Bundles / Export (Design node) + # Bundles / Export and Publish (Design node) ######################################################## def list_exported_bundles(self): @@ -958,7 +958,8 @@ def get_exported_bundle_archive_stream(self, bundle_id): def download_exported_bundle_archive_to_file(self, bundle_id, path): """ Download a bundle archive that can be deployed in a DSS automation Node into the given output file. - @param path if "-", will write to /dev/stdout + + :param path if "-", will write to /dev/stdout """ if path == "-": path= "/dev/stdout" @@ -971,6 +972,23 @@ def download_exported_bundle_archive_to_file(self, bundle_id, path): f.flush() stream.close() + def publish_bundle(self, bundle_id, published_project_key=None): + """ + Publish a bundle on the Project Deployer. + + :param string bundle_id: The identifier of the bundle + :param string published_project_key: The key of the project on the Project Deployer where the bundle will be published. + A new published project will be created if none matches the key. + If the parameter is not set, the key from the current :class:`DSSProject` is used. + + :rtype: dict + :return: a dict with info on the bundle state once published. It contains the keys "publishedOn" for the publish date, + "publishedBy" for the user who published the bundle, and "publishedProjectKey" for the key of the Project Deployer project used. + """ + params = None + if published_project_key is not None: + params = {"publishedProjectKey": published_project_key} + return self.client._perform_json("GET", "/projects/%s/bundles/%s/publish" % (self.project_key, bundle_id), params=params) ######################################################## # Bundles / Import (Automation node) diff --git a/dataikuapi/dss/projectdeployer.py b/dataikuapi/dss/projectdeployer.py index ee8919c0..6ca50917 100644 --- a/dataikuapi/dss/projectdeployer.py +++ b/dataikuapi/dss/projectdeployer.py @@ -69,7 +69,7 @@ def list_stages(self): """ Lists infrastructure stages of the Project Deployer - :rtype: a list of dict. Each dict contains a field "id" for the stage identifier and "desc" for its description. + :rtype: list of dict. Each dict contains a field "id" for the stage identifier and "desc" for its description. :rtype: list """ return self.client._perform_json("GET", "/project-deployer/stages") @@ -152,6 +152,24 @@ def get_project(self, project_key): """ return DSSProjectDeployerProject(self.client, project_key) + def upload_bundle(self, fp, project_key=None): + """ + Uploads a new version for a project from a file-like object pointing + to a bundle Zip file. + + :param string fp: A file-like object pointing to a bundle Zip file + :param string project_key: The key of the published project where the bundle will be uploaded. If the project does not exist, it is created. + If not set, the key of the bundle's source project is used. + + """ + if project_key is None: + params = None + else: + params = { + "projectKey": project_key, + } + return self.client._perform_empty("POST", + "/project-deployer/projects/bundles", params=params, files={"file":fp}) ############################################### # Infrastructures @@ -160,7 +178,7 @@ def get_project(self, project_key): class DSSProjectDeployerInfra(object): """ - A Deployment infrastructure on the Project Deployer + An Automation infrastructure on the Project Deployer Do not create this directly, use :meth:`~dataikuapi.dss.projectdeployer.DSSProjectDeployer.get_infra` """ @@ -168,9 +186,20 @@ def __init__(self, client, infra_id): self.client = client self.infra_id = infra_id + @property def id(self): return self.infra_id + def get_status(self): + """ + Returns status information about this infrastructure + + :rtype: :class:`dataikuapi.dss.projectdeployer.DSSProjectDeployerInfraStatus` + """ + light = self.client._perform_json("GET", "/project-deployer/infras/%s" % (self.infra_id)) + + return DSSProjectDeployerInfraStatus(self.client, self.infra_id, light) + def get_settings(self): """ Gets the settings of this infra. If you want to modify the settings, you need to @@ -194,7 +223,8 @@ def delete(self): class DSSProjectDeployerInfraSettings(object): - """The settings of a Project Deployer Infra. + """ + The settings of an Automation infrastructure. Do not create this directly, use :meth:`~dataikuapi.dss.projectdeployer.DSSProjectDeployerInfra.get_settings` """ @@ -213,12 +243,42 @@ def get_raw(self): return self.settings def save(self): - """Saves back these settings to the infra""" + """ + Saves back these settings to the infra + """ self.client._perform_empty( "PUT", "/project-deployer/infras/%s/settings" % (self.infra_id), body = self.settings) +class DSSProjectDeployerInfraStatus(object): + """ + The status of an Automation infrastructure. + + Do not create this directly, use :meth:`~dataikuapi.dss.projectdeployer.DSSProjectDeployerInfra.get_status` + """ + def __init__(self, client, infra_id, light_status): + self.client = client + self.infra_id = infra_id + self.light_status = light_status + + def get_deployments(self): + """ + Returns the deployments that are deployed on this infrastructure + + :returns: a list of deployments + :rtype: list of :class:`dataikuapi.dss.projectdeployer.DSSProjectDeployerDeployment` + """ + return [DSSProjectDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"]] + + def get_raw(self): + """ + Gets the raw status information. This returns a dictionary with various information about the infrastructure + + :rtype: dict + """ + return self.light_status + ############################################### # Deployments ############################################### @@ -234,11 +294,13 @@ def __init__(self, client, deployment_id): self.client = client self.deployment_id = deployment_id + @property def id(self): return self.deployment_id def get_status(self): - """Returns status information about this deployment + """ + Returns status information about this deployment :rtype: dataikuapi.dss.apideployer.DSSProjectDeployerDeploymentStatus """ @@ -302,8 +364,19 @@ def get_raw(self): """ return self.settings + @property + def bundle_id(self): + """ + Gets the bundle id currently used by this deployment. + + :rtype: str + """ + return self.settings["bundleId"] + def save(self): - """Saves back these settings to the deployment""" + """ + Saves back these settings to the deployment + """ self.client._perform_empty( "PUT", "/project-deployer/deployments/%s/settings" % (self.deployment_id), body = self.settings) @@ -332,12 +405,14 @@ def get_light(self): def get_heavy(self): """ Gets the 'heavy' (full) status. This returns a dictionary with various information about the deployment + :rtype: dict """ return self.heavy_status def get_health(self): - """Returns the health of this deployment as a string + """ + Returns the health of this deployment as a string :returns: HEALTHY if the deployment is working properly, various other status otherwise :rtype: string @@ -345,7 +420,9 @@ def get_health(self): return self.heavy_status["health"] def get_health_messages(self): - """Returns messages about the health of this deployment""" + """ + Returns messages about the health of this deployment + """ return self.heavy_status["healthMessages"] ############################################### @@ -362,6 +439,7 @@ def __init__(self, client, project_key): self.client = client self.project_key = project_key + @property def id(self): return self.project_key @@ -375,24 +453,6 @@ def get_status(self): light = self.client._perform_json("GET", "/project-deployer/projects/%s" % (self.project_key)) return DSSProjectDeployerProjectStatus(self.client, self.project_key, light) - def import_bundle(self, fp, design_node_url=None, design_node_id=None): - """ - Imports a new version for a project from a file-like object pointing - to a bundle Zip file. - :param string fp: A file-like object pointing to a bundle Zip file - :param string design_node_url: The URL of the Design node where the bundle was created - :param design_node_id: The identifier of the Design node where the bundle was created - """ - if design_node_url is None and design_node_id is None: - params = None - else: - params = { - "designNodeId": design_node_id, - "designNodeUrl": design_node_url - } - return self.client._perform_empty("POST", - "/project-deployer/projects/%s/bundles" % (self.project_key), params=params, files={"file":fp}) - def get_settings(self): """ Gets the settings of this project. If you want to modify the settings, you need to @@ -411,6 +471,7 @@ def get_settings(self): def delete_bundle(self, bundle_id): """ Deletes a bundle from this project + :param string bundle_id: The identifier of the bundle to delete """ self.client._perform_empty( @@ -425,6 +486,7 @@ def delete(self): return self.client._perform_empty( "DELETE", "/project-deployer/projects/%s" % (self.project_key)) + class DSSProjectDeployerProjectSettings(object): """The settings of a published project. @@ -445,14 +507,17 @@ def get_raw(self): return self.settings def save(self): - """Saves back these settings to the project""" + """ + Saves back these settings to the project + """ self.client._perform_empty( "PUT", "/project-deployer/projects/%s/settings" % (self.project_key), body = self.settings) class DSSProjectDeployerProjectStatus(object): - """The status of a published project. + """ + The status of a published project. Do not create this directly, use :meth:`~dataikuapi.dss.projectdeployer.DSSProjectDeployerProject.get_status` """ @@ -461,6 +526,20 @@ def __init__(self, client, project_key, light_status): self.project_key = project_key self.light_status = light_status + def get_deployments(self, infra_id=None): + """ + Returns the deployments that have been created from this published project + + :param str infra_id: Identifier of an infra, allows to only keep in the returned list the deployments on this infra. + If not set, the list contains all the deployments using this published project, across every infra of the Project Deployer. + + :returns: a list of deployments + :rtype: list of :class:`dataikuapi.dss.projectdeployer.DSSProjectDeployerDeployment` + """ + if infra_id is None: + return [DSSProjectDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"]] + return [DSSProjectDeployerDeployment(self.client, deployment["id"]) for deployment in self.light_status["deployments"] if infra_id == deployment["infraId"]] + def get_bundles(self): """ Returns the bundles that have been published on this project @@ -475,6 +554,7 @@ def get_bundles(self): def get_raw(self): """ Gets the raw status information. This returns a dictionary with various information about the project + :rtype: dict """ - return self.light_status \ No newline at end of file + return self.light_status diff --git a/dataikuapi/utils.py b/dataikuapi/utils.py index 74f15380..e4512acc 100644 --- a/dataikuapi/utils.py +++ b/dataikuapi/utils.py @@ -94,3 +94,10 @@ def str_to_bool(s): doublequote=True): yield [none_if_throws(caster)(val) for (caster, val) in dku_zip_longest(casters, uncasted_tuple)] + +class CallableStr(str): + def __init__(self, val): + self.val = val + + def __call__(self): + return self.val