Skip to content

Commit 6adcf95

Browse files
alexanpatrananos
authored andcommitted
feat: create descriptions from inventory.yaml. remove nb-api. add github action
Signed-off-by: Alexandros Patras <patras@uth.gr>
1 parent 3122b87 commit 6adcf95

18 files changed

Lines changed: 520 additions & 335 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Build & publish
2+
3+
on:
4+
workflow_dispatch:
5+
workflow_call:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
build:
12+
runs-on: ["base-dind-2204-amd64"]
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v2
16+
with:
17+
submodules: recursive
18+
19+
- name: Find SHA
20+
run: |
21+
if [[ "${{github.event.pull_request.head.sha}}" != "" ]]
22+
then
23+
echo "ARTIFACT_SHA=$(echo ${{github.event.pull_request.head.sha}})" >> $GITHUB_ENV
24+
echo "CI_COMMIT_TAG=0.0.0-${{ github.run_id }}" >> $GITHUB_ENV
25+
else
26+
echo "ARTIFACT_SHA=$(echo ${GITHUB_REF##*/})" >> $GITHUB_ENV
27+
echo "CI_COMMIT_TAG=${{ github.ref_name }}" >> $GITHUB_ENV
28+
fi
29+
30+
- name: Install python dependencies
31+
run: |
32+
sudo apt update && sudo apt install -y python3.10-venv
33+
python3 -m venv .venv
34+
. .venv/bin/activate
35+
.venv/bin/python3 -m pip install --upgrade pip
36+
if [ -f requirements.txt ]; then .venv/bin/python3 -m pip install -r requirements.txt; fi
37+
38+
#- name: Lint with flake8
39+
# run: |
40+
# # stop the build if there are Python syntax errors or undefined names
41+
# python3 -m flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
42+
# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
43+
# python3 -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
44+
45+
#- name: Test with pytest
46+
# env:
47+
# PYTHONPATH: .
48+
# run: |
49+
# python3 -m build
50+
# python3 -m pytest
51+
52+
#- name: Test with coverage
53+
# env:
54+
# PYTHONPATH: .
55+
# run: |
56+
# python3 -m pytest tests/
57+
58+
- name: Build pip package
59+
run: |
60+
. .venv/bin/activate
61+
.venv/bin/python3 -m pip install build
62+
cd agents
63+
../.venv/bin/python3 -m build
64+
VERSION=$(python3 setup.py --version)
65+
PYVER=$(python3 --version | awk '{print $2}' | awk -F\. '{print $1 $2 }')
66+
67+
# FIXME: add pypi publish step
68+
- name: Publish package
69+
#if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
70+
uses: pypa/gh-action-pypi-publish@release/v1
71+
with:
72+
password: ${{ secrets.PYPI_TOKEN }}
73+
packages-dir: agents/dist

.github/workflows/ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ jobs:
3535
uses: ./.github/workflows/build-mlsysops-pkg.yml
3636
secrets: inherit
3737

38+
build-cli-pkg:
39+
#needs: [validate-files-and-commits, lint]
40+
name: Build mlsysops CLI pkg
41+
if: |
42+
contains(github.event.pull_request.labels.*.name, 'ok-to-test') &&
43+
!contains(github.event.pull_request.labels.*.name, 'skip-build-pkg')
44+
uses: ./.github/workflows/build-cli-pkg.yml
45+
secrets: inherit
46+
3847
build-agent-containers:
3948
needs: [build-agent-pkg]
4049
name: Build containers
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# mlsysops/__init__.py
22

33
from .cli import cli
4-
5-
__version__ = "0.1.0"
4+
from .deployment import *

mlsysops-cli/mlsysops_cli/cli.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python3
2+
import traceback
23

34
import click
45
import requests
@@ -13,6 +14,8 @@
1314
deploy_node_agents,
1415
)
1516

17+
from mlsysops_cli.deployment.descriptions_util import create_app_yaml
18+
1619
# Configurable IP and PORT via environment variables
1720
IP = os.getenv("MLS_API_IP", "127.0.0.1")
1821
PORT = os.getenv("MLS_API_PORT", "8000")
@@ -313,9 +316,15 @@ def framework():
313316

314317

315318
@click.command(help="Deploy all components (core services, continuum, clusters, nodes)")
316-
def deploy_all():
319+
@click.option('--path', type=click.Path(exists=True), required=False, help='Path to the desriptions directory. It MUST include path/continuum,path/cluster,path/node')
320+
@click.option('--inventory', type=click.Path(exists=True), required=False, help='Path to the inventory YAML that was used from cluster/karmada setup ansible script.')
321+
def deploy_all(path, inventory):
322+
# Ensure only one of the --path or --uri options is provided
323+
if path and inventory:
324+
click.secho('❌ Error: Provide only --path or --uri.')
325+
return
317326
try:
318-
run_deploy_all()
327+
run_deploy_all(path, inventory)
319328
except Exception as e:
320329
click.secho(f"❌ Error during full deployment: {e}", fg='red')
321330

@@ -329,35 +338,62 @@ def deploy_services():
329338

330339

331340
@click.command(help="Deploy the continuum agent")
332-
def deploy_continuum():
341+
@click.option('--path', type=click.Path(exists=True), required=False, help='Path to the desriptions directory. It MUST include path/continuum,path/cluster,path/node')
342+
@click.option('--inventory', type=click.Path(exists=True), required=False, help='Path to the inventory YAML that was used from cluster/karmada setup ansible script.')
343+
def deploy_continuum(path, inventory):
344+
# Ensure only one of the --path or --uri options is provided
345+
if path and inventory:
346+
click.secho('❌ Error: Provide only --path or --uri.')
347+
return
333348
try:
334-
deploy_continuum_agents()
349+
deploy_continuum_agents(path, inventory)
335350
except Exception as e:
336351
click.secho(f"❌ Error during continuum agent deployment: {e}", fg='red')
337352

338353

339354
@click.command(help="Deploy the cluster agents")
340-
def deploy_cluster():
355+
@click.option('--path', type=click.Path(exists=True), required=False, help='Path to the desriptions directory. It MUST include path/continuum,path/cluster,path/node')
356+
@click.option('--inventory', type=click.Path(exists=True), required=False, help='Path to the inventory YAML that was used from cluster/karmada setup ansible script.')
357+
def deploy_cluster(path, inventory):
358+
# Ensure only one of the --path or --uri options is provided
359+
if path and inventory:
360+
click.secho('❌ Error: Provide only --path or --uri.')
361+
return
341362
try:
342-
deploy_cluster_agents()
363+
deploy_cluster_agents(path, inventory)
343364
except Exception as e:
344365
click.secho(f"❌ Error during cluster agents deployment: {e}", fg='red')
345366

346367

347368
@click.command(help="Deploy the node agents")
348-
def deploy_node():
369+
@click.option('--path', type=click.Path(exists=True), required=False, help='Path to the desriptions directory. It MUST include path/continuum,path/cluster,path/node')
370+
@click.option('--inventory', type=click.Path(exists=True), required=False, help='Path to the inventory YAML that was used from cluster/karmada setup ansible script.')
371+
def deploy_node(path, inventory):
372+
# Ensure only one of the --path or --uri options is provided
373+
if path and inventory:
374+
click.secho('❌ Error: Provide only --path or --uri.')
375+
return
376+
349377
try:
350-
deploy_node_agents()
378+
deploy_node_agents(path, inventory)
351379
except Exception as e:
352380
click.secho(f"❌ Error during node agents deployment: {e}", fg='red')
353381

382+
@click.command(help="Create a test application description using an inventory YAML.")
383+
@click.option('--inventory', type=click.Path(exists=True), required=True, help='Path to the inventory YAML that was used from cluster/karmada setup ansible script.')
384+
def create_test_app_description(inventory):
385+
try:
386+
create_app_yaml(inventory)
387+
except Exception as e:
388+
click.secho(f"❌ Error during test application descriptions creation: {e}", fg='red')
354389

355-
# Agrega los comandos al grupo 'framework'
390+
# Add commands to the 'framework' group
356391
framework.add_command(deploy_all)
357392
framework.add_command(deploy_services)
358393
framework.add_command(deploy_continuum)
359394
framework.add_command(deploy_cluster)
360395
framework.add_command(deploy_node)
396+
framework.add_command(create_test_app_description)
361397

362398
cli.add_command(framework)
363399

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .descriptions_util import *

mlsysops-cli/mlsysops_cli/deployment/deploy.py

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pathlib import Path
22
from importlib.resources import files
33
import kubernetes.client.rest
4+
import yaml
45
from jinja2 import Environment, FileSystemLoader
56
from kubernetes import client, config
67
from kubernetes.client import ApiException
@@ -9,6 +10,7 @@
910
from jinja2 import Template
1011
import subprocess
1112
from mlsysops_cli import deployment
13+
from mlsysops_cli.deployment.descriptions_util import create_cluster_yaml, create_worker_node_yaml,create_continuum_yaml
1214

1315

1416
def parse_yaml_from_file(path_obj: Path, template_variables: dict = {}) -> list | None:
@@ -264,10 +266,10 @@ def create_configmap_from_file(self, descriptions_directory, namespace, name, su
264266
Create a ConfigMap from all YAML files inside a given folder inside the package.
265267
"""
266268
files_data_object = {}
267-
269+
directory = Path(descriptions_directory)
268270
try:
269271
for suffix in suffixes:
270-
for file in descriptions_directory.glob(suffix):
272+
for file in directory.glob(suffix):
271273
print(f"Reading file: {file.name}")
272274
file_data = file.read_text()
273275
files_data_object[file.name] = file_data
@@ -485,13 +487,13 @@ def _check_required_env_vars(*required_vars):
485487
if missing:
486488
raise EnvironmentError(f"Missing required environment variables: {', '.join(missing)}")
487489

488-
def run_deploy_all():
490+
def run_deploy_all(path, inventory_path):
489491
try:
490492
print("🚀 Deploying all MLSysOps components...")
491493
deploy_core_services()
492-
deploy_continuum_agents()
493-
deploy_cluster_agents()
494-
deploy_node_agents()
494+
deploy_continuum_agents(path, inventory_path)
495+
deploy_cluster_agents(path, inventory_path)
496+
deploy_node_agents(path, inventory_path)
495497
print("✅ All components deployed successfully.")
496498
except Exception as e:
497499
print(f"❌ Error in deploy_all: {e}")
@@ -518,15 +520,30 @@ def deploy_core_services():
518520
for r in parse_yaml_from_file(redis_path, {"KARMADA_HOST_IP": os.getenv("KARMADA_HOST_IP")}):
519521
client_k8s.create_or_update(r)
520522

521-
def deploy_continuum_agents():
523+
def deploy_continuum_agents(path, inventory_path):
522524
print("🧠 Deploying Continuum Agent...")
523525
_check_required_env_vars("KARMADA_HOST_IP", "KARMADA_HOST_KUBECONFIG")
524526
client_k8s = KubernetesLibrary("apps", "v1", os.getenv("KARMADA_HOST_KUBECONFIG", "/etc/rancher/k3s/k3s.yaml"))
525527
_apply_namespace_and_rbac(client_k8s)
526528

529+
descriptions_path = os.getenv("CONTINUUM_SYSTEM_DESCRIPTIONS_PATH", "descriptions")
530+
if path:
531+
descriptions_path = path
532+
533+
if inventory_path:
534+
# build the system descriptions
535+
parent_dir = "descriptions"
536+
descriptions_path = os.path.join(parent_dir, "continuum")
537+
if not os.path.exists(parent_dir):
538+
os.makedirs(parent_dir)
539+
if not os.path.exists(descriptions_path):
540+
os.makedirs(descriptions_path)
541+
542+
543+
create_continuum_yaml(inventory_path, descriptions_path)
544+
527545
# ConfigMap descriptions
528-
desc_path = files(deployment).joinpath("descriptions/continuum")
529-
client_k8s.create_configmap_from_file(desc_path, "mlsysops-framework", "continuum-system-description")
546+
client_k8s.create_configmap_from_file(descriptions_path, "mlsysops-framework", "continuum-system-description")
530547

531548
kubeconfig_path = files(deployment).joinpath("descriptions/continuum")
532549
client_k8s.create_configmap_from_file(kubeconfig_path, "mlsysops-framework", "continuum-karmadapi-config", suffixes=["*.kubeconfig"])
@@ -536,36 +553,81 @@ def deploy_continuum_agents():
536553
for r in parse_yaml_from_file(daemonset_path):
537554
client_k8s.create_or_update(r)
538555

539-
def deploy_cluster_agents():
556+
def deploy_cluster_agents(path, inventory_path):
540557
print("🏢 Deploying Cluster Agents...")
541558
_check_required_env_vars("KARMADA_HOST_IP", "KARMADA_API_KUBECONFIG")
542559
client_karmada = KubernetesLibrary("apps", "v1", os.getenv("KARMADA_API_KUBECONFIG", "/etc/rancher/k3s/k3s.yaml"))
543560
_apply_namespace_and_rbac(client_karmada)
544561
client_karmada.apply_mlsysops_propagation_policies()
545562

563+
descriptions_path = os.getenv("CLUSTER_SYSTEM_DESCRIPTIONS_PATH", "descriptions")
564+
if path:
565+
descriptions_path = path
566+
567+
if inventory_path:
568+
# build the system descriptions
569+
parent_dir = "descriptions"
570+
descriptions_path = os.path.join(parent_dir, "cluster")
571+
if not os.path.exists(parent_dir):
572+
os.makedirs(parent_dir)
573+
if not os.path.exists(descriptions_path):
574+
os.makedirs(descriptions_path)
575+
576+
with open(inventory_path, 'r') as file:
577+
inventory = yaml.safe_load(file)
578+
579+
for cluster_name in inventory['all']['children']:
580+
try:
581+
print(f"Processing cluster: {cluster_name}")
582+
create_cluster_yaml(inventory_path, cluster_name, descriptions_path)
583+
except ValueError as e:
584+
print(f"Skipping cluster '{cluster_name}': {e}")
585+
546586
# ConfigMap
547-
desc_path = files(deployment).joinpath("descriptions/cluster")
548-
client_karmada.create_configmap_from_file(desc_path, "mlsysops-framework", "cluster-system-description")
587+
client_karmada.create_configmap_from_file(descriptions_path, "mlsysops-framework", "cluster-system-description")
549588

550589
# DaemonSet YAML
551590
daemonset_path = files(deployment).joinpath("cluster-agents-daemonset.yaml")
552591
for r in parse_yaml_from_file(daemonset_path, {"KARMADA_HOST_IP": os.getenv("KARMADA_HOST_IP")}):
553592
client_karmada.create_or_update(r)
554593

555-
def deploy_node_agents():
594+
def deploy_node_agents(path, inventory_path):
556595
print("🧱 Deploying Node Agents...")
557596
_check_required_env_vars("KARMADA_HOST_IP", "KARMADA_API_KUBECONFIG")
558597
client_karmada = KubernetesLibrary("apps", "v1", os.getenv("KARMADA_API_KUBECONFIG", "/etc/rancher/k3s/k3s.yaml"))
559598

599+
descriptions_path = os.getenv("NODE_SYSTEM_DESCRIPTIONS_PATH","descriptions")
600+
if path:
601+
descriptions_path = path
602+
603+
if inventory_path:
604+
# build the system descriptions
605+
parent_dir = "descriptions"
606+
descriptions_path = os.path.join(parent_dir,"nodes")
607+
if not os.path.exists(parent_dir):
608+
os.makedirs(parent_dir)
609+
if not os.path.exists(descriptions_path):
610+
os.makedirs(descriptions_path)
611+
612+
with open(inventory_path, 'r') as file:
613+
inventory = yaml.safe_load(file)
614+
615+
for cluster_name in inventory['all']['children']:
616+
try:
617+
print(f"Processing cluster: {cluster_name}")
618+
create_worker_node_yaml(inventory_path, cluster_name,descriptions_path)
619+
except ValueError as e:
620+
print(f"Skipping cluster '{cluster_name}': {e}")
621+
560622
# ConfigMap
561-
desc_path = files(deployment).joinpath("descriptions/node")
562-
print(desc_path)
563-
client_karmada.create_configmap_from_file(desc_path, "mlsysops-framework", "node-system-descriptions")
623+
print(f"Using node systems decriptions from {descriptions_path}")
624+
client_karmada.create_configmap_from_file(descriptions_path, "mlsysops-framework", "node-system-descriptions")
564625

565626
# DaemonSet YAML
566627
daemonset_path = files(deployment).joinpath("node-agents-daemonset.yaml")
567628
for r in parse_yaml_from_file(daemonset_path, {"KARMADA_HOST_IP": os.getenv("KARMADA_HOST_IP")}):
568629
client_karmada.create_or_update(r)
630+
569631
def _apply_namespace_and_rbac(client_instance):
570632
# Carga de namespace.yaml
571633
ns_path = files(deployment).joinpath("namespace.yaml")

mlsysops-cli/mlsysops_cli/deployment/descriptions/clusters/mls02.yaml

Lines changed: 0 additions & 3 deletions
This file was deleted.

mlsysops-cli/mlsysops_cli/deployment/descriptions/continuum/mls01.yaml

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)