## Python OSCAR client
[](https://github.com/grycap/oscar_python/actions/workflows/tests.yaml)
[](https://pypi.org/project/oscar-python/)
This package provides a client to interact with OSCAR (https://oscar.grycap.net) clusters and services. It is available on Pypi with the name [oscar-python](https://pypi.org/project/oscar-python/).
### Contents
- [Python OSCAR client](#python-oscar-client)
- [Contents](#contents)
- [Client](#client)
- [Initialize a client with basic authentication](#initialize-a-client-with-basic-authentication)
- [Initialize a client OIDC authentication](#initialize-a-client-oidc-authentication)
- [Sample usage](#sample-usage)
- [Client methods](#client-methods)
- [Cluster methods](#cluster-methods)
- [Service methods](#service-methods)
- [Logs methods](#logs-methods)
- [Storage usage](#storage-usage)
### Client
#### Initialize a client with basic authentication
``` python
options_basic_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'user':'username',
'password':'password',
'ssl':'True'}
client = Client(options = options_basic_auth)
```
#### Initialize a client OIDC authentication
If you want to use OIDC tokens to authenticate with EGI Check-In, you can use the [OIDC Agent](https://indigo-dc.gitbook.io/oidc-agent/) to create an account configuration for the EGI issuer (https://aai.egi.eu/auth/realms/egi/) and then initialize the client specifying the `shortname` of your account like follows.
``` python
options_oidc_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'shortname':'oidc-agent-shortname',
'ssl':'True'}
client = Client(options = options_oidc_auth)
```
If you already have a valid token, you can use the parameter `oidc_token` instead.
``` python
options_oidc_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'oidc_token':'token',
'ssl':'True'}
client = Client(options = options_oidc_auth)
```
An example of using a generated token is if you want to use EGI Notebooks. Since you can't use oidc-agent on the Notebook, you can make use of the generated token that EGI provides on path `/var/run/secrets/egi.eu/access_token`.
If you have a valid refresh token (long live token), you can use the parameter `refresh_token` instead.
``` python
options_oidc_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'refresh_token':'token',
'ssl':'True'}
client = Client(options = options_oidc_auth)
```
You can get a refresh token from EGI Check-In using the [Token Portal](https://aai.egi.eu/token).
In case of using other OIDC provider you must provide two additional parameters `token_endpoint`
and `scopes`:
``` python
options_oidc_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'refresh_token':'token',
'scopes': ["openid", "profile", "email"],
'token_endpoint': "http://issuer.com/token",
'client_id': "your_client_id"
'ssl':'True'}
client = Client(options = options_oidc_auth)
```
### Sample usage
- Sample code that creates a client and gets information about the cluster
``` python
from oscar_python.client import Client
options_basic_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'user':'username',
'password':'password',
'ssl':'True'}
client = Client(options = options)
# get the cluster information
try:
info = client.get_cluster_info()
print(info.text)
except Exception as err:
print("Failed with: ", err)
```
- Sample code to create a simple service with the [cowsay example](https://github.com/grycap/oscar/tree/master/examples/cowsay) and make a synchronous invocation.
``` python
from oscar_python.client import Client
options_basic_auth = {'cluster_id':'cluster-id',
'endpoint':'https://cluster-endpoint',
'user':'username',
'password':'password',
'ssl':'True'}
client = Client(options = options)
try:
client.create_service("/absolute_path/cowsay.yaml")
response = client.run_service("cowsay", input = '{"message": "Hi there"}')
if response.status_code == 200:
print(response.text)
except Exception as err:
print("Failed with: ", err)
```
### Client methods
#### Cluster methods
**get_cluster_info**
``` python
# get the cluster information
info = client.get_cluster_info() # returns an HTTP response or an HTTPError
```
**get_cluster_config**
``` python
# get the cluster config
config = client.get_cluster_config() # returns an http response or an HTTPError
```
#### Service methods
**get_service**
``` python
# get the definition of a service
service = client.get_service("service_name") # returns an http response or an HTTPError
```
**list_services**
``` python
# get a list of all the services deployed
services = client.list_services() # returns an http response or an HTTPError
```
> _Note_ : Both `path_to_fdl` and the script path inside the fdl must be absolute.
**create_service**
``` python
# create a service
err = client.create_service("path_to_fdl" | "JSON_definition") # returns nothing if the service is created or an error if something goes wrong
```
**update_service**
``` python
# update a service
err = client.update_service("service_name","path_to_fdl" | "JSON_definition") # returns nothing if the service is created or an error if something goes wrong
```
**remove_service**
``` python
# remove a service
response = client.remove_service("service_name") # returns an http response
```
**run_service**
*`input`, `output` and `timeout` are optional parameters.*
``` python
# make a synchronous execution
response = client.run_service("service_name", input="input", output="out.png", timeout=100) # returns an http response
# make an asynchronous execution
response = client.run_service("service_name", input="input", async_call=True) # returns an http response
```
#### Logs methods
**get_job_logs**
``` python
# get logs of a job
logs = client.get_job_logs("service_name", "job_id") # returns an http response
```
**list_jobs**
``` python
# get a list of jobs in a service
log_list = client.list_jobs("service_name") # returns an http response
# to get more jobs use the page parameter
log_list = client.list_jobs("service_name",page="token_to_next_page") # returns an http response
```
**remove_job**
``` python
# remove a job of a service
response = client.remove_job("service_name", "job_id") # returns an http response
```
**remove_all_jobs**
``` python
# remove all jobs in a service
response = client.remove_all_jobs("service_name") # returns an http response
```
#### Storage usage
You can create a storage object to operate over the different storage providers defined on a service with the method `create_storage_client`. This constructor returns a storage object with methos to interact with the storage providers.
The default constructor, seen as follows, will create a provider to interact with the default MinIO instance through the user's credentials.
``` python
storage_service = client.create_storage_client() # returns a storage object
```
Additionally, if you need to interact with specific storage providers defined on a service, the constructor accepts a `svc` parameter where you can state the service name from which to search for additional credentials.
``` python
storage_service = client.create_storage_client("service_name") # returns a storage object
```
> _Note_ : The `storage_provider` parameter on the storage methods follows the format: `["storage_provider_type"].["storage_provider_name"]` where `storage_provider_type` is one of the suported storage providers (minIO, S3, Onedata or webdav) and `storage_provider_name` is the identifier _(ex: minio.default)_
**list_files_from_path**
This method returns a JSON with the info except for OneData, which returns an HTTP response.
``` python
# get a list of the files of one of the service storage provider
files = storage_service.list_files_from_path("storage_provider", "remote_path") # returns json
```
**upload_file**
``` python
# upload a file from a local path to a remote path
response = storage_service.upload_file("storage_provider", "local_path", "remote_path")
```
**download_file**
``` python
# download a file from a remote path to a local path
response = storage_service.download_file("storage_provider", "local_path", "remote_path")
```
Raw data
{
"_id": null,
"home_page": null,
"name": "oscar-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "oscar, faas, serverless",
"author": "GRyCAP - I3M - UPV",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/57/9a/0c6f637b94c88804e75b3f2ba38f3c81e555ed76c3a1b33bac9490d5b824/oscar_python-1.3.3.tar.gz",
"platform": null,
"description": "## Python OSCAR client\n\n[](https://github.com/grycap/oscar_python/actions/workflows/tests.yaml)\n[](https://pypi.org/project/oscar-python/)\n\nThis package provides a client to interact with OSCAR (https://oscar.grycap.net) clusters and services. It is available on Pypi with the name [oscar-python](https://pypi.org/project/oscar-python/).\n\n### Contents\n- [Python OSCAR client](#python-oscar-client)\n - [Contents](#contents)\n - [Client](#client)\n - [Initialize a client with basic authentication](#initialize-a-client-with-basic-authentication)\n - [Initialize a client OIDC authentication](#initialize-a-client-oidc-authentication)\n - [Sample usage](#sample-usage)\n - [Client methods](#client-methods)\n - [Cluster methods](#cluster-methods)\n - [Service methods](#service-methods)\n - [Logs methods](#logs-methods)\n - [Storage usage](#storage-usage)\n\n### Client\n\n#### Initialize a client with basic authentication\n``` python\n options_basic_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'user':'username',\n 'password':'password',\n 'ssl':'True'}\n\n client = Client(options = options_basic_auth)\n```\n#### Initialize a client OIDC authentication\n\nIf you want to use OIDC tokens to authenticate with EGI Check-In, you can use the [OIDC Agent](https://indigo-dc.gitbook.io/oidc-agent/) to create an account configuration for the EGI issuer (https://aai.egi.eu/auth/realms/egi/) and then initialize the client specifying the `shortname` of your account like follows.\n\n``` python\n options_oidc_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'shortname':'oidc-agent-shortname',\n 'ssl':'True'}\n \n client = Client(options = options_oidc_auth)\n```\n\nIf you already have a valid token, you can use the parameter `oidc_token` instead.\n\n``` python\n options_oidc_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'oidc_token':'token',\n 'ssl':'True'}\n \n client = Client(options = options_oidc_auth)\n```\nAn example of using a generated token is if you want to use EGI Notebooks. Since you can't use oidc-agent on the Notebook, you can make use of the generated token that EGI provides on path `/var/run/secrets/egi.eu/access_token`.\n\nIf you have a valid refresh token (long live token), you can use the parameter `refresh_token` instead.\n\n``` python\n options_oidc_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'refresh_token':'token',\n 'ssl':'True'}\n \n client = Client(options = options_oidc_auth)\n```\n\nYou can get a refresh token from EGI Check-In using the [Token Portal](https://aai.egi.eu/token).\n\nIn case of using other OIDC provider you must provide two additional parameters `token_endpoint`\nand `scopes`:\n\n``` python\n options_oidc_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'refresh_token':'token',\n 'scopes': [\"openid\", \"profile\", \"email\"],\n 'token_endpoint': \"http://issuer.com/token\",\n 'client_id': \"your_client_id\"\n 'ssl':'True'}\n \n client = Client(options = options_oidc_auth)\n```\n\n### Sample usage\n\n- Sample code that creates a client and gets information about the cluster\n\n``` python\nfrom oscar_python.client import Client\n\noptions_basic_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'user':'username',\n 'password':'password',\n 'ssl':'True'}\n\nclient = Client(options = options)\n\n# get the cluster information\ntry:\n info = client.get_cluster_info()\n print(info.text)\nexcept Exception as err:\n print(\"Failed with: \", err)\n```\n\n- Sample code to create a simple service with the [cowsay example](https://github.com/grycap/oscar/tree/master/examples/cowsay) and make a synchronous invocation.\n\n``` python\nfrom oscar_python.client import Client\n\noptions_basic_auth = {'cluster_id':'cluster-id',\n 'endpoint':'https://cluster-endpoint',\n 'user':'username',\n 'password':'password',\n 'ssl':'True'}\n\nclient = Client(options = options)\n\ntry:\n client.create_service(\"/absolute_path/cowsay.yaml\")\n response = client.run_service(\"cowsay\", input = '{\"message\": \"Hi there\"}') \n if response.status_code == 200:\n print(response.text)\nexcept Exception as err:\n print(\"Failed with: \", err)\n```\n\n### Client methods\n\n#### Cluster methods\n\n**get_cluster_info**\n``` python\n# get the cluster information\ninfo = client.get_cluster_info() # returns an HTTP response or an HTTPError\n```\n\n**get_cluster_config**\n``` python\n# get the cluster config\nconfig = client.get_cluster_config() # returns an http response or an HTTPError\n```\n\n#### Service methods\n\n**get_service**\n``` python\n# get the definition of a service \nservice = client.get_service(\"service_name\") # returns an http response or an HTTPError\n```\n\n**list_services**\n``` python\n# get a list of all the services deployed \nservices = client.list_services() # returns an http response or an HTTPError\n```\n\n> _Note_ : Both `path_to_fdl` and the script path inside the fdl must be absolute.\n\n**create_service**\n``` python\n# create a service \nerr = client.create_service(\"path_to_fdl\" | \"JSON_definition\") # returns nothing if the service is created or an error if something goes wrong\n```\n\n**update_service**\n``` python\n# update a service \nerr = client.update_service(\"service_name\",\"path_to_fdl\" | \"JSON_definition\") # returns nothing if the service is created or an error if something goes wrong\n```\n\n**remove_service**\n``` python\n# remove a service \nresponse = client.remove_service(\"service_name\") # returns an http response\n```\n\n**run_service**\n\n *`input`, `output` and `timeout` are optional parameters.*\n\n``` python\n# make a synchronous execution \nresponse = client.run_service(\"service_name\", input=\"input\", output=\"out.png\", timeout=100) # returns an http response\n\n# make an asynchronous execution\nresponse = client.run_service(\"service_name\", input=\"input\", async_call=True) # returns an http response\n```\n\n#### Logs methods\n\n**get_job_logs**\n``` python\n# get logs of a job\nlogs = client.get_job_logs(\"service_name\", \"job_id\") # returns an http response\n```\n\n**list_jobs**\n``` python\n# get a list of jobs in a service\nlog_list = client.list_jobs(\"service_name\") # returns an http response\n# to get more jobs use the page parameter\nlog_list = client.list_jobs(\"service_name\",page=\"token_to_next_page\") # returns an http response\n```\n\n**remove_job**\n``` python\n# remove a job of a service\nresponse = client.remove_job(\"service_name\", \"job_id\") # returns an http response\n```\n\n**remove_all_jobs**\n``` python\n# remove all jobs in a service\nresponse = client.remove_all_jobs(\"service_name\") # returns an http response\n```\n\n#### Storage usage\n\nYou can create a storage object to operate over the different storage providers defined on a service with the method `create_storage_client`. This constructor returns a storage object with methos to interact with the storage providers.\n\nThe default constructor, seen as follows, will create a provider to interact with the default MinIO instance through the user's credentials. \n\n``` python\nstorage_service = client.create_storage_client() # returns a storage object\n```\nAdditionally, if you need to interact with specific storage providers defined on a service, the constructor accepts a `svc` parameter where you can state the service name from which to search for additional credentials.\n\n``` python\nstorage_service = client.create_storage_client(\"service_name\") # returns a storage object\n```\n\n> _Note_ : The `storage_provider` parameter on the storage methods follows the format: `[\"storage_provider_type\"].[\"storage_provider_name\"]` where `storage_provider_type` is one of the suported storage providers (minIO, S3, Onedata or webdav) and `storage_provider_name` is the identifier _(ex: minio.default)_\n\n**list_files_from_path**\n\nThis method returns a JSON with the info except for OneData, which returns an HTTP response.\n\n``` python\n# get a list of the files of one of the service storage provider \nfiles = storage_service.list_files_from_path(\"storage_provider\", \"remote_path\") # returns json\n```\n\n**upload_file**\n``` python\n# upload a file from a local path to a remote path \nresponse = storage_service.upload_file(\"storage_provider\", \"local_path\", \"remote_path\")\n```\n\n**download_file**\n``` python\n# download a file from a remote path to a local path \nresponse = storage_service.download_file(\"storage_provider\", \"local_path\", \"remote_path\")\n```\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Python client for OSCAR clusters",
"version": "1.3.3",
"project_urls": {
"Homepage": "https://github.com/grycap/oscar-python",
"Repository": "https://github.com/grycap/oscar-python"
},
"split_keywords": [
"oscar",
" faas",
" serverless"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ec18850054b29d7a8d6764c0415aae85b6be75cddd85608ba776a409e14aa6de",
"md5": "bc4b1270df91af157dbf814729f4e31c",
"sha256": "bcf25af20cff7a20667bd53d3ee15868be9e2e5cf37a32e8529c5796480a2199"
},
"downloads": -1,
"filename": "oscar_python-1.3.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "bc4b1270df91af157dbf814729f4e31c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 21773,
"upload_time": "2025-10-24T09:48:57",
"upload_time_iso_8601": "2025-10-24T09:48:57.900860Z",
"url": "https://files.pythonhosted.org/packages/ec/18/850054b29d7a8d6764c0415aae85b6be75cddd85608ba776a409e14aa6de/oscar_python-1.3.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "579a0c6f637b94c88804e75b3f2ba38f3c81e555ed76c3a1b33bac9490d5b824",
"md5": "c65416a6e6492139365b5fe6afbf2dd5",
"sha256": "7ab670fce193b6b7352ef8e27c56975c5d8abbd61802018cd60611cb0ebb20f7"
},
"downloads": -1,
"filename": "oscar_python-1.3.3.tar.gz",
"has_sig": false,
"md5_digest": "c65416a6e6492139365b5fe6afbf2dd5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 26212,
"upload_time": "2025-10-24T09:48:59",
"upload_time_iso_8601": "2025-10-24T09:48:59.237720Z",
"url": "https://files.pythonhosted.org/packages/57/9a/0c6f637b94c88804e75b3f2ba38f3c81e555ed76c3a1b33bac9490d5b824/oscar_python-1.3.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-24 09:48:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "grycap",
"github_project": "oscar-python",
"github_not_found": true,
"lcname": "oscar-python"
}