Esempio n. 1
0
        def get_task_result():
            response = self.call_api("get", ("tasks", namespace, task_id))
            content_disposition = response.headers.get("Content-Disposition")
            if content_disposition and content_disposition.startswith(
                    "attachment"):
                # we were sent a file to download
                filename = None
                filename_re = r'attachment\s*;\s*filename\s*=\s*"(.+)"\s*$'
                m = re.search(filename_re, content_disposition)
                if m:
                    filename = m.group(1)

                return FileDownloadResponse(
                    response.content, response.headers.get("Content-Type"),
                    filename)
            # otherwise we should have received a json
            reply = response.json()
            if reply["status"] != "ok":
                raise encapsia_api.EncapsiaApiError(response.text)
            rest_api_result = reply["result"]
            task_status = rest_api_result["status"]
            task_result = rest_api_result["result"]
            if task_status == "finished":
                return task_result
            elif task_status == "failed":
                raise encapsia_api.EncapsiaApiError(rest_api_result)
            else:
                return NoResultYet
Esempio n. 2
0
 def call_api(
     self,
     method,
     path_segments,
     data=None,
     json=None,
     return_json=False,
     check_json_status=False,
     extra_headers=None,
     expected_codes=(200, 201),
     params=None,
     stream=False,
 ):
     headers = {
         "Accept": "application/json",
         "Authorization": "Bearer {}".format(self.token),
         "User-Agent": f"encapsia-api/{encapsia_api.__version__}",
     }
     if json:
         headers["Content-type"] = "application/json"
     if extra_headers:
         headers.update(extra_headers)
     if path_segments:
         segments = [self.url, self.version]
         if isinstance(path_segments, str):
             segments.append(path_segments.lstrip("/"))
         else:
             segments.extend([s.lstrip("/") for s in path_segments])
     else:
         segments = [self.url]
     url = "/".join(segments)
     response = requests.request(
         method,
         url,
         data=data,
         json=json,
         params=params,
         headers=headers,
         verify=True,
         allow_redirects=False,
         stream=stream,
     )
     if response.status_code not in expected_codes:
         raise encapsia_api.EncapsiaApiError(
             "{} {}\nFull response:\n{}".format(
                 response.status_code,
                 response.reason,
                 (response.content or "").strip(),
             )
         )
     if not stream and return_json:
         answer = response.json()
         if check_json_status and answer["status"] != "ok":
             raise encapsia_api.EncapsiaApiError(response.text)
         return answer
     else:
         return response
Esempio n. 3
0
 def get_job_result():
     with self.call_api("get", ("tasks", namespace, task_id)) as response:
         reply = response.json()
         if reply.get("status") != "ok":
             raise encapsia_api.EncapsiaApiError(response.text)
         rest_api_result = reply["result"]
         task_status = rest_api_result["status"]
         if task_status == "finished":
             reply = self.get(("jobs", namespace, job_id))
             joblog = reply["result"]["logs"][0]
             assert joblog["status"] == "success"
             result = joblog["output"]
             if download:
                 filename = pathlib.Path(download)
                 with filename.open("wt") as f:
                     json.dump(result, f, indent=4)
                 return FileDownloadResponse(filename, "application/json")
             else:
                 return result
         elif task_status == "failed":
             raise encapsia_api.EncapsiaApiFailedTaskError(
                 "Failed Task behind the Job. See Exception payload attribute.",
                 payload=rest_api_result,
             )
         else:
             return NoResultYet
Esempio n. 4
0
 def download_blob_data(self, blob_id, fileobj=None):
     """Download blob data for given blob_id."""
     extra_headers = {"Accept": "*/*"}
     response = self.call_api(
         "get",
         ("blobs", blob_id),
         extra_headers=extra_headers,
         expected_codes=(200, 302, 404),
         stream=fileobj is not None,
     )
     if response.status_code in (302, 404):
         return None
     elif response.status_code == 200:
         if fileobj is not None:
             # NB Using shutil.copyfileobj is an attractive option, but does not
             # decode the gzip and deflate transfer-encodings...
             for chunk in response.iter_content(chunk_size=None):
                 fileobj.write(chunk)
             return None
         else:
             return response.content
     else:
         raise encapsia_api.EncapsiaApiError(
             "Unable to download blob {}: {}".format(
                 blob_id, response.status_code))
Esempio n. 5
0
 def get_result():
     reply = self.get(("dbctl", "action", name, action_id))
     rest_api_result = reply["result"]
     action_status = rest_api_result["status"]
     action_result = rest_api_result["result"]
     if action_status == "finished":
         return action_result
     elif action_status == "failed":
         raise encapsia_api.EncapsiaApiError(rest_api_result)
     else:
         return NoResultYet
Esempio n. 6
0
 def dbctl_download_data(self, handle, filename=None):
     """Download data and return (temp) filename."""
     headers = {
         "Accept": "*/*",
         "Authorization": "Bearer {}".format(self.token)
     }
     url = "/".join([self.url, self.version, "dbctl/data", handle])
     response = requests.get(url, headers=headers, verify=True, stream=True)
     if response.status_code != 200:
         raise encapsia_api.EncapsiaApiError("{} {}".format(
             response.status_code, response.reason))
     if filename is None:
         _, filename = tempfile.mkstemp()
     _stream_response_to_file(response, filename)
     return filename
Esempio n. 7
0
def discover_credentials(host=None):
    """Return (url, token) or raise EncapsiaApiError."""
    if not host:
        host = os.environ.get("ENCAPSIA_HOST")
    if host:
        store = CredentialsStore()
        try:
            url, token = store.get(host)
        except KeyError:
            raise encapsia_api.EncapsiaApiError(
                f"Cannot find entry for '{host}' in encapsia credentials file."
            )
    else:
        url, token = _get_env_var("ENCAPSIA_URL"), _get_env_var(
            "ENCAPSIA_TOKEN")
    return url, token
Esempio n. 8
0
 def download_blob_data(self, blob_id):
     """Download blob data for given blob_id."""
     extra_headers = {"Accept": "*/*"}
     response = self.call_api(
         "get",
         ("blobs", blob_id),
         extra_headers=extra_headers,
         expected_codes=(200, 302, 404),
     )
     if response.status_code == 200:
         return response.content
     elif response.status_code in (302, 404):
         return None
     else:
         raise encapsia_api.EncapsiaApiError(
             "Unable to download blob {}: {}".format(blob_id, response.status_code)
         )
Esempio n. 9
0
def download_to_file(url, token, target_file=None, cleanup=True):
    """Context manager for downloading a fixed file to a target_file."""
    if target_file is None:
        filename = pathlib.Path(tempfile.mkstemp()[1])
    else:
        filename = pathlib.Path(target_file)
    try:
        headers = {"Accept": "*/*", "Authorization": "Bearer {}".format(token)}
        response = requests.get(url, headers=headers, verify=True, stream=True)
        if response.status_code != 200:
            raise encapsia_api.EncapsiaApiError("{} {}".format(
                response.status_code, response.reason))
        stream_response_to_file(response, filename)
        yield filename
    finally:
        if cleanup:
            filename.unlink()
Esempio n. 10
0
    def dbctl_download_data(self, handle, filename=None):
        """Download data and return (temp) filename."""
        headers = {
            "Accept": "*/*",
            "Authorization": "Bearer {}".format(self.token)
        }
        url = "/".join([self.url, self.version, "dbctl/data", handle])
        response = requests.get(url, headers=headers, verify=True, stream=True)
        if response.status_code != 200:
            raise encapsia_api.EncapsiaApiError("{} {}".format(
                response.status_code, response.reason))

        if filename is None:
            _, filename = tempfile.mkstemp()
        with open(filename, "wb") as f:
            for chunk in response.iter_content(chunk_size=1024):
                f.write(chunk)
        return filename
Esempio n. 11
0
 def get_task_result():
     with self.call_api(
         "get", ("tasks", namespace, task_id), stream=True
     ) as response:
         if response.headers.get("Content-type") == "application/json":
             reply = response.json()
             if reply.get("status") != "ok":
                 raise encapsia_api.EncapsiaApiError(response.text)
             rest_api_result = reply["result"]
             task_status = rest_api_result["status"]
             task_result = rest_api_result["result"]
             if task_status == "finished":
                 if download:
                     filename = pathlib.Path(download)
                     with filename.open("wt") as f:
                         json.dump(task_result, f, indent=4)
                     return FileDownloadResponse(filename, "application/json")
                 else:
                     return task_result
             elif task_status == "failed":
                 raise encapsia_api.EncapsiaApiFailedTaskError(
                     "Failed Task. See Exception payload attribute.",
                     payload=rest_api_result,
                 )
             else:
                 return NoResultYet
         else:
             # Stream the response directly to the given file.
             # Note we don't care whether this is JSON, CSV, or some other type.
             if download:
                 filename = pathlib.Path(download)
                 stream_response_to_file(response, filename)
                 return FileDownloadResponse(
                     filename, response.headers.get("Content-type")
                 )
             else:
                 return response.text
Esempio n. 12
0
def _get_env_var(name):
    try:
        return os.environ[name]
    except KeyError:
        raise encapsia_api.EncapsiaApiError(
            f"Environment variable {name} does not exist!")