Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/SK-1127 | add session_id flag #742

Merged
merged 11 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 44 additions & 10 deletions fedn/cli/client_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,47 @@ def list_clients(ctx, protocol: str, host: str, port: str, token: str = None, n_
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing clients: {url}\n")
click.echo(f"Headers: {headers}")

try:
response = requests.get(url, headers=headers)
print_response(response, "clients")
print_response(response, "clients", None)
except requests.exceptions.ConnectionError:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should handle more than just ConnectionError, there are plenty of other error related to http requests. You don't have do do this know but make an other issue of it. For example create a utility function that handles all requests and checks the response for error:

import requests
from requests.exceptions import HTTPError, Timeout, ConnectionError, RequestException

def make_request(method, url, **kwargs):
"""
A reusable function to handle HTTP(S) requests with error handling.

Args:
    method (str): HTTP method (e.g., 'GET', 'POST').
    url (str): The URL for the request.
    **kwargs: Additional arguments passed to `requests.request()`.

Returns:
    dict: A dictionary with the response data or an error message.
"""
try:
    response = requests.request(method, url, **kwargs)
    response.raise_for_status()
    # Assuming JSON response, adjust if needed
    return {"success": True, "data": response.json()}
except HTTPError as http_err:
    return {"success": False, "error": f"HTTP error occurred: {http_err}"}
except Timeout:
    return {"success": False, "error": "The request timed out"}
except ConnectionError:
    return {"success": False, "error": "Connection error occurred"}
except RequestException as req_err:
    return {"success": False, "error": f"Request error: {req_err}"}
except Exception as e:
    return {"success": False, "error": f"Unexpected error: {e}"}

click.echo(f"Error: Could not connect to {url}")

@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-id", "--id", required=True, help="Client ID")
@client_cmd.command("get")
@click.pass_context
def get_client(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
Wrede marked this conversation as resolved.
Show resolved Hide resolved
"""Return:
------
- result: client with given id

@client_cmd.command("start")
"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="clients")
headers = {}


_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "client", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@client_cmd.command("start-v1")
@click.option("-d", "--discoverhost", required=False, help="Hostname for discovery services(reducer).")
@click.option("-p", "--discoverport", required=False, help="Port for discovery services (reducer).")
@click.option("--token", required=False, help="Set token provided by reducer if enabled")
Expand Down Expand Up @@ -208,18 +238,18 @@ def _complement_client_params(config: dict):
click.echo(f"Protocol missing, complementing api_url with protocol: {result}")


@client_cmd.command("start-v2")
@client_cmd.command("start")
@click.option("-u", "--api-url", required=False, help="Hostname for fedn api.")
@click.option("-p", "--api-port", required=False, help="Port for discovery services (reducer).")
@click.option("--token", required=False, help="Set token provided by reducer if enabled")
@click.option("-n", "--name", required=False, default="client" + str(uuid.uuid4())[:8])
@click.option("-n", "--name", required=False)
@click.option("-i", "--client-id", required=False)
@click.option("--local-package", is_flag=True, help="Enable local compute package")
@click.option("-c", "--preferred-combiner", type=str, required=False, default="", help="name of the preferred combiner")
@click.option("--combiner", type=str, required=False, default=None, help="Skip combiner assignment from discover service and attach directly to combiner host.")
@click.option("--combiner-port", type=str, required=False, default=None, help="Combiner port, need to be used with --combiner")
@click.option("-va", "--validator", required=False, default=True)
@click.option("-tr", "--trainer", required=False, default=True)
@click.option("-va", "--validator", required=False, default=None)
@click.option("-tr", "--trainer", required=False, default=None)
@click.option("-h", "--helper_type", required=False, default=None)
@click.option("-in", "--init", required=False, default=None, help="Set to a filename to (re)init client from file state.")
@click.pass_context
Expand All @@ -239,8 +269,6 @@ def client_start_v2_cmd(
helper_type: str,
init: str,
):
click.echo(click.style("\n*** fedn client start-v2 is experimental ***\n", blink=True, bold=True, fg="red"))

package = "local" if local_package else "remote"

config = {
Expand Down Expand Up @@ -291,6 +319,8 @@ def client_start_v2_cmd(
config["name"] = name
if config["name"]:
click.echo(f"Input param name: {name} overrides value from file")
elif config["name"] is None:
config["name"] = "client" + str(uuid.uuid4())[:8]

if client_id and client_id != "":
config["client_id"] = client_id
Expand All @@ -316,11 +346,15 @@ def client_start_v2_cmd(
config["validator"] = validator
if config["validator"] is not None:
click.echo(f"Input param validator: {validator} overrides value from file")
elif config["validator"] is None:
config["validator"] = True

if trainer is not None:
config["trainer"] = trainer
if config["trainer"] is not None:
click.echo(f"Input param trainer: {trainer} overrides value from file")
elif config["trainer"] is None:
config["trainer"] = True

if helper_type and helper_type != "":
config["helper_type"] = helper_type
Expand Down
37 changes: 34 additions & 3 deletions fedn/cli/combiner_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,42 @@ def list_combiners(ctx, protocol: str, host: str, port: str, token: str = None,
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing combiners: {url}\n")
click.echo(f"Headers: {headers}")

try:
response = requests.get(url, headers=headers)
print_response(response, "combiners")
print_response(response, "combiners", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-id", "--id", required=True, help="Combiner ID")
@combiner_cmd.command("get")
@click.pass_context
def get_combiner(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
"""Return:
------
- result: combiner with given id

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="combiners")
headers = {}


_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "combiner", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
47 changes: 43 additions & 4 deletions fedn/cli/model_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ def model_cmd(ctx):
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-session_id", "--session_id", required=False, help="models in session with given session id")
@click.option("--n_max", required=False, help="Number of items to list")
@model_cmd.command("list")
@click.pass_context
def list_models(ctx, protocol: str, host: str, port: str, token: str = None, n_max: int = None):
def list_models(ctx, protocol: str, host: str, port: str, token: str = None, session_id: str = None, n_max: int = None):
"""Return:
------
- count: number of models
- result: list of models

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="models")


headers = {}

if n_max:
Expand All @@ -38,11 +41,47 @@ def list_models(ctx, protocol: str, host: str, port: str, token: str = None, n_m
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing models: {url}\n")
click.echo(f"Headers: {headers}")
if session_id:
url = f"{url}?session_id={session_id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "models", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-id", "--id", required=True, help="Model ID")
@model_cmd.command("get")
@click.pass_context
def get_model(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
"""Return:
------
- result: model with given id

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="models")


headers = {}


_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "models")
print_response(response, "model", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
37 changes: 34 additions & 3 deletions fedn/cli/package_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,42 @@ def list_packages(ctx, protocol: str, host: str, port: str, token: str = None, n
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing packages: {url}\n")
click.echo(f"Headers: {headers}")

try:
response = requests.get(url, headers=headers)
print_response(response, "packages")
print_response(response, "packages", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-id", "--id", required=True, help="Package ID")
@package_cmd.command("get")
@click.pass_context
def get_package(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
"""Return:
------
- result: package with given id

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="packages")
headers = {}


_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "package", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
47 changes: 43 additions & 4 deletions fedn/cli/round_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ def round_cmd(ctx):
@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-session_id", "--session_id", required=False, help="Rounds in session with given session id")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("--n_max", required=False, help="Number of items to list")
@round_cmd.command("list")
@click.pass_context
def list_rounds(ctx, protocol: str, host: str, port: str, token: str = None, n_max: int = None):
def list_rounds(ctx, protocol: str, host: str, port: str, token: str = None, session_id: str = None, n_max: int = None):
"""Return:
------
- count: number of rounds
- result: list of rounds

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="rounds")

headers = {}

if n_max:
Expand All @@ -38,11 +40,48 @@ def list_rounds(ctx, protocol: str, host: str, port: str, token: str = None, n_m
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing rounds: {url}\n")
click.echo(f"Headers: {headers}")
if session_id:
url = f"{url}?round_config.session_id={session_id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "rounds")
print_response(response, "rounds", None)

except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-id", "--id", required=True, help="Round ID")
@click.option("-t", "--token", required=False, help="Authentication token")
@round_cmd.command("get")
@click.pass_context
def get_round(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
"""Return:
------
- result: round with given id

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="rounds")

headers = {}


_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "round", id)

except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
36 changes: 33 additions & 3 deletions fedn/cli/session_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,41 @@ def list_sessions(ctx, protocol: str, host: str, port: str, token: str = None, n
if _token:
headers["Authorization"] = _token

click.echo(f"\nListing sessions: {url}\n")
click.echo(f"Headers: {headers}")

try:
response = requests.get(url, headers=headers)
print_response(response, "sessions")
print_response(response, "sessions", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
@click.option("-H", "--host", required=False, default=CONTROLLER_DEFAULTS["host"], help="Hostname of controller (api)")
@click.option("-P", "--port", required=False, default=CONTROLLER_DEFAULTS["port"], help="Port of controller (api)")
@click.option("-t", "--token", required=False, help="Authentication token")
@click.option("-id", "--id", required=True, help="Session ID")
@session_cmd.command("get")
@click.pass_context
def get_session(ctx, protocol: str, host: str, port: str, token: str = None, id: str = None):
"""Return:
------
- result: session with given session id

"""
url = get_api_url(protocol=protocol, host=host, port=port, endpoint="sessions")
headers = {}

_token = get_token(token)

if _token:
headers["Authorization"] = _token

if id:
url = f"{url}{id}"


try:
response = requests.get(url, headers=headers)
print_response(response, "session", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
Loading
Loading