Skip to content
35 changes: 22 additions & 13 deletions oscar_python/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import base64
import json
import os
import time as _time
import requests
import liboidcagent as agent
_DEFAULT_TIMEOUT = 60
Expand All @@ -32,21 +33,29 @@ def make_request(c, path, method, **kwargs):

url = c.endpoint+path

if method in ["post", "put"]:
if "token" in kwargs.keys() and kwargs["token"]:
headers = get_headers_with_token(kwargs["token"])
req_kwargs = {"headers": headers, "verify": c.ssl, "timeout": timeout}
if "data" in kwargs.keys() and kwargs["data"]:
req_kwargs["data"] = kwargs["data"]
result = requests.request(method, url, **req_kwargs)
else:
result = requests.request(method, url, headers=headers, verify=c.ssl, timeout=timeout)
max_retries = 3
for attempt in range(max_retries):
if method in ["post", "put", "delete"]:
if "token" in kwargs.keys() and kwargs["token"]:
headers = get_headers_with_token(kwargs["token"])
req_kwargs = {"headers": headers, "verify": c.ssl, "timeout": timeout}
if "data" in kwargs.keys() and kwargs["data"]:
req_kwargs["data"] = kwargs["data"]
req_kwargs["headers"]["Content-Type"] = "application/json"
result = requests.request(method, url, **req_kwargs)
else:
result = requests.request(method, url, headers=headers, verify=c.ssl, timeout=timeout)

if "handle" in kwargs.keys() and kwargs["handle"] is False:
return result
if "handle" in kwargs.keys() and kwargs["handle"] is False:
return result

result.raise_for_status()
return result
if result.status_code == 500 and method == "put":
if attempt < max_retries - 1:
_time.sleep(0.5 * (2 ** attempt))
continue

result.raise_for_status()
return result


def get_headers(c):
Expand Down
28 changes: 28 additions & 0 deletions oscar_python/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
_BUCKETS_PATH = "/system/buckets"
_METRICS_PATH = "/system/metrics"
_QUOTAS_USER_PATH = "/system/quotas/user"
_FEDERATION_PATH = "/system/federation"


# _JOB_PATH = "/job"
Expand Down Expand Up @@ -340,3 +341,30 @@ def get_user_quota(self, user_id):
def update_user_quota(self, user_id, cpu, memory):
data = json.dumps({"cpu": cpu, "memory": memory})
return utils.make_request(self, _QUOTAS_USER_PATH + "/" + user_id, _PUT, data=data)

""" Get federation members for a service """
def get_federation(self, service_name):
return utils.make_request(self, _FEDERATION_PATH + "/" + service_name, _GET)

""" Add federation members to a service """
def add_federation_members(self, service_name, members, clusters=None, storage_providers=None):
data = {"members": members}
if clusters:
data["clusters"] = clusters
if storage_providers:
data["storage_providers"] = storage_providers
return utils.make_request(self, _FEDERATION_PATH + "/" + service_name, _POST, data=json.dumps(data))

""" Update federation members of a service """
def update_federation_members(self, service_name, members, update, clusters=None, storage_providers=None):
data = {"members": members, "update": update}
if clusters:
data["clusters"] = clusters
if storage_providers:
data["storage_providers"] = storage_providers
return utils.make_request(self, _FEDERATION_PATH + "/" + service_name, _PUT, data=json.dumps(data))

""" Remove federation members from a service """
def remove_federation_members(self, service_name, members, delete=False):
data = {"members": members, "delete": delete}
return utils.make_request(self, _FEDERATION_PATH + "/" + service_name, _DELETE, data=json.dumps(data))
88 changes: 88 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,91 @@ def test_update_user_quota(options):
client.update_user_quota("test_user", "2", "4Gi")
mock_request.assert_called_once_with(client, "/system/quotas/user/test_user", "put",
data=json.dumps({"cpu": "2", "memory": "4Gi"}))


def test_get_federation(options):
client = Client(options)
with patch('oscar_python._utils.make_request') as mock_request:
client.get_federation("test_service")
mock_request.assert_called_once_with(client, "/system/federation/test_service", "get")


def test_add_federation_members(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
with patch('oscar_python._utils.make_request') as mock_request:
client.add_federation_members("test_service", members)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "post",
data=json.dumps({"members": members}))


def test_add_federation_members_with_clusters(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
clusters = {"c1": {"endpoint": "https://c1.com", "auth_user": "u", "auth_password": "p"}}
with patch('oscar_python._utils.make_request') as mock_request:
client.add_federation_members("test_service", members, clusters=clusters)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "post",
data=json.dumps({"members": members, "clusters": clusters}))


def test_add_federation_members_with_storage_providers(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
clusters = {"c1": {"endpoint": "https://c1.com", "auth_user": "u", "auth_password": "p"}}
storage_providers = {"minio": {"my-minio": {"endpoint": "https://minio.com", "access_key": "ak", "secret_key": "sk"}}}
with patch('oscar_python._utils.make_request') as mock_request:
client.add_federation_members("test_service", members, clusters=clusters,
storage_providers=storage_providers)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "post",
data=json.dumps({"members": members, "clusters": clusters,
"storage_providers": storage_providers}))


def test_update_federation_members(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
update = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 5}]
with patch('oscar_python._utils.make_request') as mock_request:
client.update_federation_members("test_service", members, update)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "put",
data=json.dumps({"members": members, "update": update}))


def test_update_federation_members_with_clusters(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
update = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 5}]
clusters = {"c1": {"endpoint": "https://c1.com", "auth_user": "u", "auth_password": "new"}}
storage_providers = {"minio": {"my-minio": {"endpoint": "https://minio.com", "access_key": "ak", "secret_key": "sk"}}}
with patch('oscar_python._utils.make_request') as mock_request:
client.update_federation_members("test_service", members, update,
clusters=clusters, storage_providers=storage_providers)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "put",
data=json.dumps({"members": members, "update": update,
"clusters": clusters, "storage_providers": storage_providers}))


def test_remove_federation_members(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
with patch('oscar_python._utils.make_request') as mock_request:
client.remove_federation_members("test_service", members)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "delete",
data=json.dumps({"members": members, "delete": False}))


def test_remove_federation_members_with_delete(options):
client = Client(options)
members = [{"type": "oscar", "cluster_id": "c1", "service_name": "s1", "priority": 0}]
with patch('oscar_python._utils.make_request') as mock_request:
client.remove_federation_members("test_service", members, delete=True)
mock_request.assert_called_once_with(
client, "/system/federation/test_service", "delete",
data=json.dumps({"members": members, "delete": True}))
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class MockClient:
assert response.status_code == 200
mock_request.assert_called_once_with(
"post", "http://test.com/test",
headers={"Authorization": "Bearer test_token"},
headers={"Authorization": "Bearer test_token", "Content-Type": "application/json"},
verify=True, data="test_data", timeout=60)


Expand Down
Loading