diff --git a/.env.template b/.env.template index ce0011a..b3dd903 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,6 @@ REGISTRY_URL= REGISTRY_USER= REGISTRY_PASSWORD= -PARALLEL_BUILD= \ No newline at end of file +PARALLEL_BUILD= +NATS_HOST= +NATS_PORT= \ No newline at end of file diff --git a/infra/wasmcloud/wasmcloud-edge-host/README.md b/infra/wasmcloud/wasmcloud-edge-host/README.md index a745570..9316ef0 100644 --- a/infra/wasmcloud/wasmcloud-edge-host/README.md +++ b/infra/wasmcloud/wasmcloud-edge-host/README.md @@ -16,7 +16,7 @@ nast server check connection Creare l'host wasmcloud con il comando ```bash -wash up -d +wash up -d --multi-local ``` Controllare il corretto deployment dell'host ```bash diff --git a/pelato.py b/pelato.py index 4db4c59..3a6c5c7 100644 --- a/pelato.py +++ b/pelato.py @@ -1,7 +1,11 @@ import argparse import src +from dotenv import load_dotenv + def main(): + load_dotenv() + parser = argparse.ArgumentParser( description="Generate, build and deploy WASM components written in go" ) diff --git a/project/tasks/danano.go b/project/tasks/danano.go new file mode 100644 index 0000000..2b4ee72 --- /dev/null +++ b/project/tasks/danano.go @@ -0,0 +1,12 @@ +package main + +import ( + +) + +func exec_task(arg string) string{ + + response := "" + arg + + return response +} \ No newline at end of file diff --git a/project/tasks/task1.go b/project/tasks/task1.go index b778dc4..88dfe7e 100644 --- a/project/tasks/task1.go +++ b/project/tasks/task1.go @@ -6,7 +6,7 @@ import ( func exec_task(arg string) string{ - response := "" + arg + response := "Ciao danano " + arg return response } \ No newline at end of file diff --git a/project/workflow.yaml b/project/workflow.yaml index 09d6040..49c5799 100644 --- a/project/workflow.yaml +++ b/project/workflow.yaml @@ -1,11 +1,21 @@ +project_name: Test tasks: - - name: Data Aggregation # Displayed name - type: processor_nats # Used to select template - code: task1.go # Go code file inside tasks/ dir - target: # Where the component will be deployed + - name: Data Aggregation + type: producer_nats + code: task1.go + targets: - edge - cloud - source_topic: temp_sensor # Source NATS topic - dest_topic: aggregated_data # Destination NATS topic - component_name: data_aggregation # Component name displayed in the OCI artifact + source_topic: temp_sensor + dest_topic: aggregated_data + component_name: data_aggregation + version: 1.0.0 + - name: Aiutatemi + type: processor_nats + code: danano.go + targets: + - edge + source_topic: test + dest_topic: temp_sensor + component_name: test_producer version: 1.0.0 \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 512f56c..7ee4ead 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,8 +1,7 @@ -from dotenv import load_dotenv import os - import src.code_generator.generator as code_generator import src.wasm_builder.build as wasm_builder +import src.component_deploy.deploy as deployer class Pelato: def __init__(self): @@ -10,12 +9,13 @@ class Pelato: self.setup_vars() def setup_vars(self): - load_dotenv() self.registry_url = os.getenv('REGISTRY_URL') self.reg_user = os.getenv('REGISTRY_USER') self.reg_pass = os.getenv('REGISTRY_PASSWORD') self.detached = os.getenv('PARALLEL_BUILD') + self.nats_host = os.getenv('NATS_HOST') + self.nats_port = os.getenv('NATS_PORT') def generate(self, project_dir): code_generator.generate(project_dir, self.registry_url) @@ -24,7 +24,14 @@ class Pelato: wasm_builder.build_project(project_dir, self.reg_user, self.reg_pass, self.detached) def deploy(self, project_dir): - print(f"Deploying WASM components for project {project_dir}") - + deployer.deploy_components(project_dir, self.nats_host, self.nats_port, self.detached) + def all(self, project_dir): - print(f"Doing everything for project {project_dir}") \ No newline at end of file + + print('-------------------------------------------') + print(f"Starting PELATO for project {project_dir}") + print('-------------------------------------------') + + self.generate(project_dir) + self.build(project_dir) + self.deploy(project_dir) \ No newline at end of file diff --git a/src/code_generator/templates/processor_nats/wadm.yaml b/src/code_generator/templates/processor_nats/wadm.yaml index ffd48b4..65b849a 100644 --- a/src/code_generator/templates/processor_nats/wadm.yaml +++ b/src/code_generator/templates/processor_nats/wadm.yaml @@ -7,7 +7,7 @@ spec: - name: {{ component_name }} type: component properties: - image: "{{ registry_url }}/{{ component_name }}:{{ version }}" + image: {{ registry_url }}/{{ component_name }}:{{ version }} id: stream traits: - type: link diff --git a/src/code_generator/templates/producer_nats/wadm.yaml b/src/code_generator/templates/producer_nats/wadm.yaml index b983c5b..9229bbc 100644 --- a/src/code_generator/templates/producer_nats/wadm.yaml +++ b/src/code_generator/templates/producer_nats/wadm.yaml @@ -7,7 +7,7 @@ spec: - name: {{ component_name }} type: component properties: - image: "{{ registry_url }}/{{ component_name }}:{{ version }}" + image: {{ registry_url }}/{{ component_name }}:{{ version }} id: producer traits: - type: spreadscaler diff --git a/src/component_deploy/deploy.py b/src/component_deploy/deploy.py new file mode 100644 index 0000000..eec5aab --- /dev/null +++ b/src/component_deploy/deploy.py @@ -0,0 +1,83 @@ +import docker +import os +import logging +import yaml + +def deploy_components(project_dir, nats_host, nats_port, detached): + + # Check if the project directory is valid + if not os.path.exists(f"{project_dir}/gen"): + logging.error(f"Project directory is not valid") + return + + print('Deploying WASM components') + + # Docker client + client = docker.from_env() + + # Build the images for the project if they don't exist + try: + client.images.get("wash-deploy-image:latest") + except docker.errors.ImageNotFound: + + print(' - Building wash-deploy-image from Dockerfile...') + client.images.build( + path="src/component_deploy/docker", + dockerfile="deploy.Dockerfile", + tag="wash-deploy-image:latest" + ) + + try: + wait_list = [] + + for task in os.listdir(f"{project_dir}/gen"): + __deploy_wadm(f"{project_dir}/gen/{task}", client, nats_host, nats_port, detached, wait_list) + + if detached == 'True': + + print('Waiting for deployment...') + for container in wait_list: + try: + client.containers.get(container).wait() + except Exception: + continue + + except Exception as e: + logging.error(f"Error deploying project: {e}") + return + + print("Project built successfully") + +def __deploy_wadm(task_dir, client, nats_host, nats_port, detached, wait_list): + + wadm = __parse_yaml(f"{task_dir}/wadm.yaml") + + path = os.path.abspath(task_dir) + + name = wadm['spec']['components'][0]['name'] + '-deploy' + + # Build the wasm module + print(f" - Deploying WASM module {name}") + container = client.containers.run( + "wash-deploy-image:latest", + environment=[f'WASMCLOUD_CTL_HOST={nats_host}', + f'WASMCLOUD_CTL_PORT={nats_port}'], + volumes={path: {'bind': '/app', 'mode': 'rw'}}, + remove=True, + detach=True, + name=name + ) + + if detached == 'False': + container.wait() + else: + wait_list.append(name) + + +def __parse_yaml(yaml_file): + with open(yaml_file, 'r') as stream: + try: + return yaml.safe_load(stream) + except yaml.YAMLError as exc: + print(exc) + return None \ No newline at end of file diff --git a/src/wasm_builder/docker/deploy.Dockerfile b/src/component_deploy/docker/deploy.Dockerfile similarity index 100% rename from src/wasm_builder/docker/deploy.Dockerfile rename to src/component_deploy/docker/deploy.Dockerfile diff --git a/src/wasm_builder/build.py b/src/wasm_builder/build.py index 2b25bc2..aced835 100644 --- a/src/wasm_builder/build.py +++ b/src/wasm_builder/build.py @@ -10,6 +10,8 @@ def build_project(project_dir, reg_user, reg_pass, detached): logging.error(f"Project directory is not valid") return + print('Building WASM components') + # Docker client client = docker.from_env() @@ -17,6 +19,8 @@ def build_project(project_dir, reg_user, reg_pass, detached): try: client.images.get("wash-build-image:latest") except docker.errors.ImageNotFound: + + print(' - Building wash-build-image from Dockerfile...') client.images.build( path="src/wasm_builder/docker", dockerfile="build.Dockerfile", @@ -24,21 +28,34 @@ def build_project(project_dir, reg_user, reg_pass, detached): ) try: + wait_list = [] + for task in os.listdir(f"{project_dir}/gen"): - __build_wasm(f"{project_dir}/gen/{task}", client, reg_user, reg_pass, detached) + __build_wasm(f"{project_dir}/gen/{task}", client, reg_user, reg_pass, detached, wait_list) + + if detached == 'True': + + print('Waiting for build to finish...') + for container in wait_list: + try: + client.containers.get(container).wait() + except Exception: + continue + except Exception as e: logging.error(f"Error building project: {e}") return print("Project built successfully") -def __build_wasm(task_dir, client, reg_user, reg_pass, detached): +def __build_wasm(task_dir, client, reg_user, reg_pass, detached, wait_list): wadm = __parse_yaml(f"{task_dir}/wadm.yaml") path = os.path.abspath(task_dir) oci_url = wadm['spec']['components'][0]['properties']['image'] + name = wadm['spec']['components'][0]['name'] + '-build' # Build the wasm module print(f" - Building WASM module {oci_url}") @@ -49,11 +66,14 @@ def __build_wasm(task_dir, client, reg_user, reg_pass, detached): f'WASH_REG_PASSWORD={reg_pass}'], volumes={path: {'bind': '/app', 'mode': 'rw'}}, remove=True, - detach=True + detach=True, + name=name ) if detached == 'False': container.wait() + else: + wait_list.append(name) def __parse_yaml(yaml_file):