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

Feature/SK-1229 | Project resource for CLI extension #784

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
32 changes: 5 additions & 27 deletions fedn/cli/client_cmd.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import uuid

import click
import requests

from fedn.cli.main import main
from fedn.cli.shared import CONTROLLER_DEFAULTS, apply_config, get_api_url, get_token, print_response
from fedn.cli.shared import CONTROLLER_DEFAULTS, apply_config, get_response, print_response
from fedn.common.exceptions import InvalidClientConfig
from fedn.network.clients.client import Client
from fedn.network.clients.client_v2 import Client as ClientV2
Expand Down Expand Up @@ -49,22 +48,13 @@ def list_clients(ctx, protocol: str, host: str, port: str, token: str = None, n_
- result: list of clients

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

if n_max:
headers["X-Limit"] = n_max

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

try:
response = requests.get(url, headers=headers)
print_response(response, "clients", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
response = get_response(protocol=protocol, host=host, port=port, endpoint="clients", token=token, headers=headers, usr_api=False, usr_token=False)
print_response(response, "clients", None)


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
Expand All @@ -80,20 +70,8 @@ def get_client(ctx, protocol: str, host: str, port: str, token: str = None, id:
- result: client with given id

"""
_url = get_api_url(protocol=protocol, host=host, port=port, endpoint="clients")
url = f"{_url}{id}"
headers = {}

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

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}")
response = get_response(protocol=protocol, host=host, port=port, endpoint=f"clients/{id}", token=token, headers={}, usr_api=False, usr_token=False)
print_response(response, "client", id)


@client_cmd.command("start-v1")
Expand Down
32 changes: 5 additions & 27 deletions fedn/cli/combiner_cmd.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import uuid

import click
import requests

from .main import main
from .shared import CONTROLLER_DEFAULTS, apply_config, get_api_url, get_token, print_response
from .shared import CONTROLLER_DEFAULTS, apply_config, get_response, print_response


@main.group("combiner")
Expand Down Expand Up @@ -77,22 +76,13 @@ def list_combiners(ctx, protocol: str, host: str, port: str, token: str = None,
- result: list of combiners

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

if n_max:
headers["X-Limit"] = n_max

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

try:
response = requests.get(url, headers=headers)
print_response(response, "combiners", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
response = get_response(protocol=protocol, host=host, port=port, endpoint="combiners", token=token, headers=headers, usr_api=False, usr_token=False)
print_response(response, "combiners", None)


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
Expand All @@ -108,17 +98,5 @@ def get_combiner(ctx, protocol: str, host: str, port: str, token: str = None, id
- result: combiner with given id

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

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

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}")
response = get_response(protocol=protocol, host=host, port=port, endpoint=f"combiners/{id}", token=token, headers={}, usr_api=False, usr_token=False)
print_response(response, "combiner", id)
91 changes: 51 additions & 40 deletions fedn/cli/login_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

import click
import requests
import yaml

from .main import main
from .shared import STUDIO_DEFAULTS, get_api_url, get_token
from .shared import STUDIO_DEFAULTS, get_response, set_context

# Replace this with the platform's actual login endpoint
home_dir = os.path.expanduser("~")
Expand All @@ -20,13 +19,13 @@ def login_cmd(ctx):


@login_cmd.command("login")
@click.option("-", "--name", required=False, default=None, help="username in studio")
@click.option("-pw", "--password", required=False, default=None, help="password in studio")
@click.option("-n", "--username", required=False, default=None, help="username in studio")
KatHellg marked this conversation as resolved.
Show resolved Hide resolved
@click.option("-P", "--password", required=False, default=None, help="password in studio")
@click.option("-p", "--protocol", required=False, default=STUDIO_DEFAULTS["protocol"], help="Communication protocol of studio (api)")
@click.option("-H", "--host", required=False, default=STUDIO_DEFAULTS["host"], help="Hostname of studio (api)")
@click.pass_context
def login_cmd(ctx, protocol: str, host: str, username: str, password: str):
"""Logging into FEDn Studio"""
"""Login to FEDn Studio"""
# Step 1: Display welcome message
click.secho("Welcome to Scaleout FEDn!", fg="green")

Expand Down Expand Up @@ -57,50 +56,62 @@ def login_cmd(ctx, protocol: str, host: str, username: str, password: str):
context_path = os.path.join(home_dir, ".fedn")
if not os.path.exists(context_path):
os.makedirs(context_path)
try:
with open(f"{context_path}/context.yaml", "w") as yaml_file:
yaml.dump(context_data, yaml_file, default_flow_style=False) # Add access and refresh tokens to context yaml file
except Exception as e:
print(f"Error: Failed to write to YAML file. Details: {e}")
set_context(context_path, context_data)
else:
click.secho(f"Unexpected error: {response.text}", fg="red")
click.secho(f"Unexpected error: {response.status_code}", fg="red")


def get_context(response, protocol, host):
KatHellg marked this conversation as resolved.
Show resolved Hide resolved
"""Generates content for context file with the following data:
User tokens: access and refresh token to authenticate user towards Studio
Active project tokens: access and refresh token to authenticate user towards controller
Active project id: slug of active project
Active project url: controller url of active project
"""
context_data = {"User tokens": {}, "Active project tokens": {}, "Active project id": {}, "Active project url": {}}
user_token_data = response.json()
if user_token_data.get("access"):
context_data["User tokens"] = user_token_data
studio_api = True
url_projects = get_api_url(protocol=protocol, host=host, port=None, endpoint="projects", usr_api=studio_api)
headers_projects = {}
user_access_token = user_token_data.get("access")
_token = get_token(user_access_token, True)
if _token:
headers_projects["Authorization"] = _token

try:
response_projects = requests.get(url_projects, headers=headers_projects)
response_projects = get_response(
protocol=protocol,
host=host,
port=None,
endpoint="projects",
token=user_access_token,
headers=headers_projects,
usr_api=studio_api,
usr_token=True,
)
if response_projects.status_code == 200:
projects_response_json = response_projects.json()
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url_projects}")

slug = projects_response_json[0].get("slug")
headers_projects["X-Project-Slug"] = slug
url_project_token = get_api_url(protocol=protocol, host=host, port=None, endpoint="admin-token", usr_api=studio_api)
print(url_project_token)
try:
response_project_tokens = requests.get(url_project_token, headers=headers_projects)
project_tokens = response_project_tokens.json()
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url_project_token}")

controller_url = f"{protocol}://{host}/{slug}-fedn-reducer"
context_data = {
"User tokens": user_token_data,
"Active project tokens": project_tokens,
"Active project slug": slug,
"Active project url": controller_url,
}
click.secho("Login successful!", fg="green")
return context_data
if len(projects_response_json) > 0:
id = projects_response_json[0].get("slug")
context_data["Active project id"] = id
headers_projects["X-Project-Slug"] = id
response_project_tokens = get_response(
protocol=protocol,
host=host,
port=None,
endpoint="admin-token",
token=user_access_token,
headers=headers_projects,
usr_api=studio_api,
usr_token=False,
)
if response_project_tokens.status_code == 200:
project_tokens = response_project_tokens.json()
context_data["Active project tokens"] = project_tokens
controller_url = f"{protocol}://{host}/{id}-fedn-reducer"
context_data["Active project url"] = controller_url
click.secho("Login successful!", fg="green")
else:
click.secho(f"Unexpected error: {response_project_tokens.status_code}", fg="red")
else:
click.secho(f"Unexpected error: {response_projects.status_code}", fg="red")
else:
click.secho("Login failed. Please check your credentials.", fg="red")

return context_data
44 changes: 10 additions & 34 deletions fedn/cli/model_cmd.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import click
import requests

from .main import main
from .shared import CONTROLLER_DEFAULTS, get_api_url, get_token, print_response
from .shared import CONTROLLER_DEFAULTS, get_response, print_response


@main.group("model")
Expand All @@ -16,7 +15,7 @@ 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("-s", "--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
Expand All @@ -27,26 +26,18 @@ def list_models(ctx, protocol: str, host: str, port: str, token: str = None, ses
- result: list of models

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

headers = {}

if n_max:
headers["X-Limit"] = n_max

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

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}")
response = get_response(
protocol=protocol, host=host, port=port, endpoint=f"models/?session_id={session_id}", token=token, headers=headers, usr_api=False, usr_token=False
)
else:
response = get_response(protocol=protocol, host=host, port=port, endpoint="models", token=token, headers=headers, usr_api=False, usr_token=False)
print_response(response, "models", None)


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
Expand All @@ -62,20 +53,5 @@ def get_model(ctx, protocol: str, host: str, port: str, token: str = None, id: s
- result: model with given id

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

headers = {}

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

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

try:
response = requests.get(url, headers=headers)
print_response(response, "model", id)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
response = get_response(protocol=protocol, host=host, port=port, endpoint=f"models/{id}", token=token, headers={}, usr_api=False, usr_token=False)
print_response(response, "model", id)
32 changes: 5 additions & 27 deletions fedn/cli/package_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
import tarfile

import click
import requests

from fedn.common.log_config import logger

from .main import main
from .shared import CONTROLLER_DEFAULTS, get_api_url, get_token, print_response
from .shared import CONTROLLER_DEFAULTS, get_response, print_response


@main.group("package")
Expand Down Expand Up @@ -54,22 +53,13 @@ def list_packages(ctx, protocol: str, host: str, port: str, token: str = None, n
- result: list of packages

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

if n_max:
headers["X-Limit"] = n_max

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

try:
response = requests.get(url, headers=headers)
print_response(response, "packages", None)
except requests.exceptions.ConnectionError:
click.echo(f"Error: Could not connect to {url}")
response = get_response(protocol=protocol, host=host, port=port, endpoint="packages", token=token, headers=headers, usr_api=False, usr_token=False)
print_response(response, "packages", None)


@click.option("-p", "--protocol", required=False, default=CONTROLLER_DEFAULTS["protocol"], help="Communication protocol of controller (api)")
Expand All @@ -85,17 +75,5 @@ def get_package(ctx, protocol: str, host: str, port: str, token: str = None, id:
- result: package with given id

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

_token = get_token(token, False)

if _token:
headers["Authorization"] = _token

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}")
response = get_response(protocol=protocol, host=host, port=port, endpoint=f"packages/{id}", token=token, headers={}, usr_api=False, usr_token=False)
print_response(response, "package", id)
Loading
Loading