diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7cfaa7a8..115097a0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,6 +14,18 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.testing.pytestArgs": [ + "--ignore=desired_state_generator/test/integration", + "--ignore=runtime_k3d/test/integration", + "--ignore=runtime_kanto/test/integration", + "--ignore=runtime_local/test/integration", + "." + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, "python.pythonPath": "/usr/bin/python3", "python.defaultInterpreterPath": "/usr/bin/python3", // Only Flake8 is used as linter and static code analyzer, as faster tool @@ -33,12 +45,10 @@ }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ - "dbaeumer.vscode-eslint", "ms-azuretools.vscode-dapr", "ms-azuretools.vscode-docker", "ms-python.python", "cschleiden.vscode-github-actions", - "pspester.pester-test", "rpdswtk.vsmqtt", "dotjoshjohnson.xml", "ms-kubernetes-tools.vscode-kubernetes-tools", @@ -49,6 +59,7 @@ ] } }, + "onCreateCommand": "bash .devcontainer/scripts/post-create.sh", // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode" } diff --git a/.devcontainer/scripts/post-create.sh b/.devcontainer/scripts/post-create.sh new file mode 100755 index 00000000..cc51592f --- /dev/null +++ b/.devcontainer/scripts/post-create.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2023 Robert Bosch GmbH +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +echo "#######################################################" +echo "### Install python requirements ###" +echo "#######################################################" +# Update pip before installing requirements +pip3 install --upgrade pip +for package in runtime_k3d runtime_kanto runtime_local desired_state_generator; do + + REQUIREMENTS="$package/src/requirements.txt" + if [ -f $REQUIREMENTS ]; then + pip3 install -r $REQUIREMENTS + fi + REQUIREMENTS="$package/test/requirements.txt" + if [ -f $REQUIREMENTS ]; then + pip3 install -r $REQUIREMENTS + fi + +done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 403903bc..25a92934 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,11 +50,9 @@ jobs: - name: Install required packages run: | - pip install -e velocitas_lib - pip install -r runtime-k3d/src/requirements.txt - pip install -r runtime-k3d/test/requirements.txt - pip install -r runtime-local/test/requirements.txt - pip install -r velocitas_lib/test/requirements.txt + pip install -r runtime_k3d/src/requirements.txt + pip install -r runtime_k3d/test/requirements.txt + pip install -r runtime_local/test/requirements.txt - name: unit tests shell: bash @@ -62,7 +60,7 @@ jobs: pytest --ignore-glob='*integration*' --override-ini junit_family=xunit1 --junit-xml=./results/UnitTest/junit.xml \ --cov . \ --cov-report=xml:results/CodeCoverage/cobertura-coverage.xml \ - --cov-branch ./runtime-k3d/test ./runtime-local/test ./velocitas_lib/test + --cov-branch ./runtime_k3d/test ./runtime_local/test ./desired_state_generator/test - name: Publish Unit Test Results uses: mikepenz/action-junit-report@v3 @@ -96,8 +94,8 @@ jobs: - name: Set commit id run: | - NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime-local/test/.velocitas.json)" - echo "${NEW_CONFIG}" > runtime-local/test/.velocitas.json + NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime_local/test/.velocitas.json)" + echo "${NEW_CONFIG}" > runtime_local/test/.velocitas.json - name: Install required packages run: | @@ -106,12 +104,12 @@ jobs: - name: Init velocitas project run: | - cd runtime-local/test + cd runtime_local/test velocitas init -v - - name: Run integration tests for runtime-local + - name: Run integration tests for runtime_local run: | - cd runtime-local/test + cd runtime_local/test pip install -r requirements.txt pytest -s ./integration/integration_test.py @@ -120,7 +118,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: "Log files local" - path: runtime-local/test/logs/runtime-local + path: runtime_local/test/logs run-k3d-integration-tests: name: Run Integration Tests for k3d @@ -137,8 +135,8 @@ jobs: - name: Set commit id run: | - NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime-k3d/test/.velocitas.json)" - echo "${NEW_CONFIG}" > runtime-k3d/test/.velocitas.json + NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime_k3d/test/.velocitas.json)" + echo "${NEW_CONFIG}" > runtime_k3d/test/.velocitas.json - name: Install required packages run: | @@ -149,12 +147,12 @@ jobs: - name: Init velocitas project run: | - cd runtime-k3d/test + cd runtime_k3d/test velocitas init -v - name: Run integration tests for k3d run: | - cd runtime-k3d/test + cd runtime_k3d/test pip install -r requirements.txt pytest -s ./integration/integration_test.py @@ -163,7 +161,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: "Log files K3D" - path: runtime-k3d/test/logs/runtime-k3d + path: runtime_k3d/test/logs run-kanto-integration-tests: name: Run Integration Tests for kanto @@ -180,8 +178,8 @@ jobs: - name: Set commit id run: | - NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime-kanto/test/.velocitas.json)" - echo "${NEW_CONFIG}" > runtime-kanto/test/.velocitas.json + NEW_CONFIG="$(jq --arg GITHUB_SHA "$GITHUB_SHA" '.packages[0].version |= $GITHUB_SHA' runtime_kanto/test/.velocitas.json)" + echo "${NEW_CONFIG}" > runtime_kanto/test/.velocitas.json - name: Install required packages run: | @@ -192,7 +190,7 @@ jobs: wget https://github.com/eclipse-kanto/kanto/releases/download/v0.1.0-M3/kanto_0.1.0-M3_linux_x86_64.deb && \ sudo apt install ./kanto_0.1.0-M3_linux_x86_64.deb - pip install -r runtime-kanto/test/requirements.txt + pip install -r runtime_kanto/test/requirements.txt - name: Stop Kanto services run: | @@ -208,12 +206,12 @@ jobs: - name: Init velocitas project run: | - cd runtime-kanto/test + cd runtime_kanto/test velocitas init -v - name: Run integration tests for kanto run: | - cd runtime-kanto/test + cd runtime_kanto/test # the socket on the ci is different to the devcontainer sudo ln -s /run/containerd/containerd.sock /run/docker/containerd/containerd.sock pytest -s -x ./integration/integration_test.py @@ -224,4 +222,4 @@ jobs: with: name: "Log files Kanto" path: | - runtime-kanto/test/logs + runtime_kanto/test/logs diff --git a/.gitignore b/.gitignore index f4184a68..92e4f840 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ .DS_Store __pycache__ -runtime-k3d/src/runtime/deployment/config/helm/templates/values.yaml +runtime_k3d/src/runtime/deployment/config/helm/templates/values.yaml *.egg-info dist build logs results -helm +.coverage +tmp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0bd529d..67f4ff3a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: - id: end-of-file-fixer - id: check-yaml args: [--allow-multiple-documents] - exclude: ^runtime-k3d/src/runtime/deployment/config/helm/templates/|^runtime-k3d/src/app_deployment/config/helm/templates/|^config/feedercan/ + exclude: ^runtime_k3d/src/runtime/deployment/config/helm/templates/|^runtime_k3d/src/app_deployment/config/helm/templates/|^config/feedercan/ - id: check-added-large-files - repo: https://github.com/PyCQA/isort @@ -42,11 +42,11 @@ repos: # rev: "v1.2.0" # hooks: # - id: mypy - # args: [runtime-k3d, runtime-local] + # args: [runtime_k3d, runtime_local] # language: system # pass_filenames: false - # - repo: https://github.com/pycqa/pydocstyle - # rev: 6.3.0 - # hooks: - # - id: pydocstyle + - repo: https://github.com/pycqa/pydocstyle + rev: 6.3.0 + hooks: + - id: pydocstyle diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..30628763 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Debug Tests", + "type": "python", + "request": "launch", + "program": "${file}", + "purpose": [ + "debug-test" + ], + "console": "integratedTerminal", + "justMyCode": false + } + ] +} diff --git a/README.md b/README.md index 83541905..010a4a72 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ A Velocitas CLI package containing all available and supported Velocitas runtime This package contains the following runtimes: -* [Local](./runtime-local/README.md) -* [Kubernetes (K3D)](./runtime-k3d/README.md) -* [Kanto](./runtime-kanto/README.md) +* [Local](./runtime_local/README.md) +* [Kubernetes (K3D)](./runtime_k3d/README.md) +* [Kanto](./runtime_kanto/README.md) ## Runtime Configuration: `runtime.json` @@ -54,6 +54,12 @@ Function | Description :---|:--- `$pathInWorkspaceOrPackage( )` | Resolves a path dynamically either to the local project workspace, if the file is available or falls back to a file in the package repository. If none of these files is available an exception is raised. +## Deployment spec generators + +This package contains the following generators: + +* [Desired State Generator](./desired_state_generator/README.md) + ## Development hints To create a better local environment, you can execute `source ./set_cli_env.sh` to export all CLI provided variables to test your scripts without invoking them via CLI exec. diff --git a/desired_state_generator/README.md b/desired_state_generator/README.md new file mode 100644 index 00000000..2fe62999 --- /dev/null +++ b/desired_state_generator/README.md @@ -0,0 +1,3 @@ +# Desired State Generator + +Generate a desired state manifest to be used by [ETAS' PANTARIS](https://www.etas.com/en/products/pantaris-products.php) solution. diff --git a/runtime-k3d/__init__.py b/desired_state_generator/__init__.py similarity index 100% rename from runtime-k3d/__init__.py rename to desired_state_generator/__init__.py diff --git a/runtime-k3d/src/__init__.py b/desired_state_generator/src/__init__.py similarity index 100% rename from runtime-k3d/src/__init__.py rename to desired_state_generator/src/__init__.py diff --git a/desired_state_generator/src/gen_desired_state.py b/desired_state_generator/src/gen_desired_state.py new file mode 100644 index 00000000..1ee59e50 --- /dev/null +++ b/desired_state_generator/src/gen_desired_state.py @@ -0,0 +1,190 @@ +# Copyright (c) 2023 Robert Bosch GmbH +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import hashlib +import json +import os +import re +import tempfile +from typing import Any, Dict, List, Optional + +import velocitas_lib +import velocitas_lib.services + +VSS_SOURCE_DEFAULT_ID = "vss-source-default" +VSS_SOURCE_CUSTOM_ID = "vss-source-custom" +DATABROKER_ID = "data-broker-grpc" +GRPC_INTERFACE_ID = "grpc-interface" + +VELOCITAS_IF_VSI = "vehicle-signal-interface" +VELOCITAS_IF_PUBSUB = "pubsub" +VELOCITAS_IF_GRPC = "grpc-interface" + + +def is_uri(path: str) -> bool: + """Check if the provided path is a URI. + + Args: + path (str): The path to check. + + Returns: + bool: True if the path is a URI. False otherwise. + """ + return re.match(r"(\w+)\:\/\/(\w+)", path) is not None + + +def parse_vehicle_signal_interface(config: Dict[str, Any]) -> List[str]: + """Parse the vehicle signal interface config. + + Args: + config (Dict[str, Any]): The json-config of the interface, + as defined in the appManifest.json. + + Returns: + List[str]: A list of requirements defined by the config. + """ + requirements = [] + src = str(config["src"]) + vss_release_prefix = ( + "https://github.com/COVESA/vehicle_signal_specification/releases/download/" + ) + version = "" + if vss_release_prefix in src: + version = src.removeprefix(vss_release_prefix).split("/")[0] + requirements.append(f"{VSS_SOURCE_DEFAULT_ID}:{version}") + else: + version = get_md5_from_file_content(src) + requirements.append(f"{VSS_SOURCE_CUSTOM_ID}:{version}") + + requirements.append(f"{DATABROKER_ID}:v1") + + datapoints = config["datapoints"]["required"] + for datapoint in datapoints: + path = str(datapoint["path"]).lower().replace(".", "-") + access = datapoint["access"] + requirements.append(f"vss-{access}-{path}:{version}") + + return requirements + + +def parse_grpc_interface(config: Dict[str, Any]) -> str: + """Parse the grpc interface config. + + Args: + config (Dict[str, Any]): The json-config of the interface, + as defined in the appManifest.json. + + Returns: + str: The requirement with md5-hash of the proto-file as version. + """ + src = str(config["src"]) + + return f"{GRPC_INTERFACE_ID}:{get_md5_from_file_content(src)}" + + +def get_md5_from_file_content(src: str) -> str: + """Get the md5-hash of the contents of a file defined by a source. + + Args: + src (str): The source of the file. Can either be a local file-path or an URI + + Returns: + str: The md5-hash of the file. + """ + file_path = src + if is_uri(src): + file_path = os.path.join(tempfile.TemporaryDirectory().name, "tmp") + velocitas_lib.download_file(src, file_path) + + md5 = hashlib.md5(usedforsecurity=False) + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + md5.update(chunk) + + return md5.hexdigest() + + +def parse_interfaces(interfaces: List[Dict[str, Any]]) -> List[str]: + """Parse the defined interfaces. + + Args: + interfaces (List[Dict[str, Any]])): The json-array of interfaces, + as defined in the appManifest.json. + + Returns: + List[str]: A list of requirements defined by the interface definitions. + """ + requirements = [] + for interface in interfaces: + interface_type = interface["type"] + if interface_type == VELOCITAS_IF_VSI: + requirements += parse_vehicle_signal_interface(interface["config"]) + elif interface_type == VELOCITAS_IF_PUBSUB: + requirements.append("mqtt:v5") + elif interface_type == VELOCITAS_IF_GRPC: + requirements.append(parse_grpc_interface(interface["config"])) + + return requirements + + +def main(source: str, output_file_path: Optional[str] = None): + imageName = source.split(":")[0].split("/")[-1] + version = source.split(":")[1] + + app_manifest = velocitas_lib.get_app_manifest() + appName = app_manifest["name"] + interfaces = app_manifest["interfaces"] + + requirements = [] + requirements += parse_interfaces(interfaces) + + if output_file_path is None: + output_file_path = velocitas_lib.get_workspace_dir() + output_file_path = f"{output_file_path}/{appName.lower()}_manifest_{version}.json" + + data = { + "name": appName, + "source": source, + "type": "container", + "requires": requirements, + "provides": [f"{imageName}:{version}"], + } + with open( + output_file_path, + "w", + encoding="utf-8", + ) as f: + json.dump(data, f) + + +if __name__ == "__main__": + os.environ["mockFilePath"] = "mock.py" + parser = argparse.ArgumentParser("generate-desired-state") + parser.add_argument( + "-o", + "--output-file-path", + type=str, + required=False, + help="Path to the folder where the manifest should be placed.", + ) + parser.add_argument( + "-s", + "--source", + type=str, + required=True, + help="The URL of the image including the tag.", + ) + args = parser.parse_args() + main(args.source, args.output_file_path) diff --git a/desired_state_generator/src/requirements.txt b/desired_state_generator/src/requirements.txt new file mode 100644 index 00000000..ee428502 --- /dev/null +++ b/desired_state_generator/src/requirements.txt @@ -0,0 +1 @@ +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-local/test/requirements.txt b/desired_state_generator/test/requirements.txt similarity index 50% rename from runtime-local/test/requirements.txt rename to desired_state_generator/test/requirements.txt index c562f220..805eb2a9 100644 --- a/runtime-local/test/requirements.txt +++ b/desired_state_generator/test/requirements.txt @@ -1,2 +1 @@ pytest==7.2.1 -velocitas_lib diff --git a/desired_state_generator/test/test_gen_desired_state.py b/desired_state_generator/test/test_gen_desired_state.py new file mode 100644 index 00000000..721c5712 --- /dev/null +++ b/desired_state_generator/test/test_gen_desired_state.py @@ -0,0 +1,44 @@ +# Copyright (c) 2023 Robert Bosch GmbH +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# flake8: noqa: E402 +import os +import sys +from pathlib import Path + +import pytest + +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "src")) +from gen_desired_state import get_md5_from_file_content, is_uri + + +@pytest.mark.parametrize( + "src", + [ + f"{Path.cwd()}/LICENSE", + "https://raw.githubusercontent.com/eclipse-velocitas/devenv-runtimes/main/LICENSE", + ], +) +def test_get_md5_for_file(src): + hash = get_md5_from_file_content(src) + # generated with https://emn178.github.io/online-tools/md5_checksum.html + assert hash == "86d3f3a95c324c9479bd8986968f4327" + + +def test_is_uri__true(): + assert is_uri("https://github.com/eclipse-velocitas") + + +def test_is_uri__false(): + assert not is_uri(f"{Path.cwd()}/LICENSE") diff --git a/manifest.json b/manifest.json index 444e22a2..61f6cd7b 100644 --- a/manifest.json +++ b/manifest.json @@ -7,41 +7,45 @@ "programs": [ { "id": "ensure-dapr", - "executable": "./runtime-local/src/ensure-dapr.sh" + "executable": "./runtime_local/src/ensure-dapr.sh" }, { "id": "run-service", "executable": "python3", "args": [ - "./runtime-local/src/run_service.py" + "./runtime_local/src/run_service.py" ] }, { "id": "up", "executable": "python3", "args": [ - "./runtime-local/src/runtime-up.py" + "./runtime_local/src/runtime-up.py" ] }, { "id": "install-deps", "executable": "python3", "args": [ - "./runtime-local/src/install_deps.py" + "-m", + "pip", + "install", + "-r", + "./runtime_local/src/requirements.txt" ] }, { "id": "run-vehicle-app", "executable": "python3", "args": [ - "./runtime-local/src/run-vehicle-app.py" + "./runtime_local/src/run-vehicle-app.py" ] }, { "id": "run-dapr-sidecar", "executable": "python3", "args": [ - "./runtime-local/src/run-dapr-sidecar.py" + "./runtime_local/src/run-dapr-sidecar.py" ] } ], @@ -89,35 +93,39 @@ "id": "install-deps", "executable": "python3", "args": [ - "./runtime-k3d/src/install_deps.py" + "-m", + "pip", + "install", + "-r", + "./runtime_k3d/src/requirements.txt" ] }, { "id": "up", "executable": "python3", "args": [ - "./runtime-k3d/src/runtime/runtime-up.py" + "./runtime_k3d/src/runtime/runtime-up.py" ] }, { "id": "down", "executable": "python3", "args": [ - "./runtime-k3d/src/runtime/runtime-down.py" + "./runtime_k3d/src/runtime/runtime-down.py" ] }, { "id": "generate-podspec", "executable": "python3", "args": [ - "./runtime-k3d/src/runtime/deployment/gen_podspec.py" + "./runtime_k3d/src/runtime/deployment/gen_podspec.py" ] }, { "id": "generate-helm", "executable": "python3", "args": [ - "./runtime-k3d/src/runtime/deployment/gen_helm.py" + "./runtime_k3d/src/runtime/deployment/gen_helm.py" ] } ], @@ -162,14 +170,14 @@ "id": "build-vehicleapp", "executable": "python3", "args": [ - "./runtime-k3d/src/app_deployment/build_vehicleapp.py" + "./runtime_k3d/src/app_deployment/build_vehicleapp.py" ] }, { "id": "deploy-vehicleapp", "executable": "python3", "args": [ - "./runtime-k3d/src/app_deployment/deploy_vehicleapp.py" + "./runtime_k3d/src/app_deployment/deploy_vehicleapp.py" ] }, { @@ -203,21 +211,25 @@ "id": "install-deps", "executable": "python3", "args": [ - "./runtime-kanto/src/install_deps.py" + "-m", + "pip", + "install", + "-r", + "./runtime_kanto/src/requirements.txt" ] }, { "id": "up", "executable": "python3", "args": [ - "./runtime-kanto/src/runtime/runtime_up.py" + "./runtime_kanto/src/runtime/runtime_up.py" ] }, { "id": "down", "executable": "python3", "args": [ - "./runtime-kanto/src/runtime/runtime_down.py" + "./runtime_kanto/src/runtime/runtime_down.py" ] } ], @@ -250,14 +262,14 @@ "id": "build-vehicleapp", "executable": "python3", "args": [ - "./runtime-kanto/src/app_deployment/build_vehicleapp.py" + "./runtime_kanto/src/app_deployment/build_vehicleapp.py" ] }, { "id": "deploy-vehicleapp", "executable": "python3", "args": [ - "./runtime-kanto/src/app_deployment/deploy_vehicleapp.py" + "./runtime_kanto/src/app_deployment/deploy_vehicleapp.py" ] } ], @@ -281,6 +293,44 @@ "default": "mock.py" } ] + }, + { + "id": "pantaris-integration", + "alias": "pantaris", + "type": "setup", + "programs": [ + { + "id": "install-deps", + "executable": "python3", + "args": [ + "-m", + "pip", + "install", + "-r", + "./desired_state_generator/src/requirements.txt" + ] + }, + { + "id": "generate-desired-state", + "executable": "python3", + "args": [ + "./desired_state_generator/src/gen_desired_state.py" + ] + } + ], + "variables": [ + { + "name": "runtimeFilePath", + "type": "string", + "description": "Path to the file describing your custom runtime configuration.", + "default": "runtime.json" + } + ], + "onPostInit": [ + { + "ref": "install-deps" + } + ] } ] } diff --git a/runtime-k3d/src/install_deps.py b/runtime-k3d/src/install_deps.py deleted file mode 100644 index 5b943691..00000000 --- a/runtime-k3d/src/install_deps.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH and Microsoft Corporation -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -"""Provides methods and functions to download and install dependencies.""" - -import os -import subprocess -import sys - - -def get_script_path() -> str: - """Return the absolute path to the directory the invoked Python script - is located in.""" - return os.path.dirname(os.path.realpath(sys.argv[0])) - - -def pip(args: list[str]) -> None: - """Invoke the pip process with the given arguments.""" - subprocess.check_call([sys.executable, "-m", "pip", *args]) - - -def install_packages(): - """Install all required Python packages.""" - script_path = get_script_path() - pip(["install", "-r", f"{script_path}/requirements.txt"]) - - -def install_velocitas_lib(): - """Install the velocitas lib.""" - script_path = get_script_path() - pip(["install", "-e", f"{script_path}/../../velocitas_lib"]) - - -if __name__ == "__main__": - install_velocitas_lib() - install_packages() diff --git a/runtime-k3d/src/requirements.txt b/runtime-k3d/src/requirements.txt deleted file mode 100644 index 2a788a63..00000000 --- a/runtime-k3d/src/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -yaspin==2.3.0 -ruamel.yaml==0.17.32 -velocitas_lib diff --git a/runtime-kanto/src/install_deps.py b/runtime-kanto/src/install_deps.py deleted file mode 100644 index 5b943691..00000000 --- a/runtime-kanto/src/install_deps.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH and Microsoft Corporation -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -"""Provides methods and functions to download and install dependencies.""" - -import os -import subprocess -import sys - - -def get_script_path() -> str: - """Return the absolute path to the directory the invoked Python script - is located in.""" - return os.path.dirname(os.path.realpath(sys.argv[0])) - - -def pip(args: list[str]) -> None: - """Invoke the pip process with the given arguments.""" - subprocess.check_call([sys.executable, "-m", "pip", *args]) - - -def install_packages(): - """Install all required Python packages.""" - script_path = get_script_path() - pip(["install", "-r", f"{script_path}/requirements.txt"]) - - -def install_velocitas_lib(): - """Install the velocitas lib.""" - script_path = get_script_path() - pip(["install", "-e", f"{script_path}/../../velocitas_lib"]) - - -if __name__ == "__main__": - install_velocitas_lib() - install_packages() diff --git a/runtime-kanto/src/requirements.txt b/runtime-kanto/src/requirements.txt deleted file mode 100644 index e6029b02..00000000 --- a/runtime-kanto/src/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -yaspin==2.3.0 -velocitas_lib diff --git a/runtime-local/src/install_deps.py b/runtime-local/src/install_deps.py deleted file mode 100644 index 5b943691..00000000 --- a/runtime-local/src/install_deps.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH and Microsoft Corporation -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -"""Provides methods and functions to download and install dependencies.""" - -import os -import subprocess -import sys - - -def get_script_path() -> str: - """Return the absolute path to the directory the invoked Python script - is located in.""" - return os.path.dirname(os.path.realpath(sys.argv[0])) - - -def pip(args: list[str]) -> None: - """Invoke the pip process with the given arguments.""" - subprocess.check_call([sys.executable, "-m", "pip", *args]) - - -def install_packages(): - """Install all required Python packages.""" - script_path = get_script_path() - pip(["install", "-r", f"{script_path}/requirements.txt"]) - - -def install_velocitas_lib(): - """Install the velocitas lib.""" - script_path = get_script_path() - pip(["install", "-e", f"{script_path}/../../velocitas_lib"]) - - -if __name__ == "__main__": - install_velocitas_lib() - install_packages() diff --git a/runtime-local/src/requirements.txt b/runtime-local/src/requirements.txt deleted file mode 100644 index e6029b02..00000000 --- a/runtime-local/src/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -yaspin==2.3.0 -velocitas_lib diff --git a/runtime-k3d/README.md b/runtime_k3d/README.md similarity index 100% rename from runtime-k3d/README.md rename to runtime_k3d/README.md diff --git a/runtime-k3d/src/app_deployment/__init__.py b/runtime_k3d/__init__.py similarity index 100% rename from runtime-k3d/src/app_deployment/__init__.py rename to runtime_k3d/__init__.py diff --git a/runtime-k3d/src/runtime/__init__.py b/runtime_k3d/src/__init__.py similarity index 100% rename from runtime-k3d/src/runtime/__init__.py rename to runtime_k3d/src/__init__.py diff --git a/runtime-k3d/src/runtime/deployment/__init__.py b/runtime_k3d/src/app_deployment/__init__.py similarity index 100% rename from runtime-k3d/src/runtime/deployment/__init__.py rename to runtime_k3d/src/app_deployment/__init__.py diff --git a/runtime-k3d/src/app_deployment/build_vehicleapp.py b/runtime_k3d/src/app_deployment/build_vehicleapp.py similarity index 95% rename from runtime-k3d/src/app_deployment/build_vehicleapp.py rename to runtime_k3d/src/app_deployment/build_vehicleapp.py index 916840aa..bc01316a 100644 --- a/runtime-k3d/src/app_deployment/build_vehicleapp.py +++ b/runtime_k3d/src/app_deployment/build_vehicleapp.py @@ -12,17 +12,16 @@ # # SPDX-License-Identifier: Apache-2.0 -from yaspin import yaspin - from velocitas_lib import create_log_file from velocitas_lib.docker import build_vehicleapp_image +from yaspin import yaspin def build_vehicleapp(): """Build VehicleApp docker image and display the progress using a spinner.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("build-vapp", "runtime-k3d") + log_output = create_log_file("build-vapp", "runtime_k3d") with yaspin(text="Building VehicleApp...", color="cyan") as spinner: try: status = "> Building VehicleApp image" diff --git a/runtime-k3d/src/app_deployment/config/helm/.helmignore b/runtime_k3d/src/app_deployment/config/helm/.helmignore similarity index 100% rename from runtime-k3d/src/app_deployment/config/helm/.helmignore rename to runtime_k3d/src/app_deployment/config/helm/.helmignore diff --git a/runtime-k3d/src/app_deployment/config/helm/Chart.yaml b/runtime_k3d/src/app_deployment/config/helm/Chart.yaml similarity index 100% rename from runtime-k3d/src/app_deployment/config/helm/Chart.yaml rename to runtime_k3d/src/app_deployment/config/helm/Chart.yaml diff --git a/runtime-k3d/src/app_deployment/config/helm/templates/_helpers.tpl b/runtime_k3d/src/app_deployment/config/helm/templates/_helpers.tpl similarity index 100% rename from runtime-k3d/src/app_deployment/config/helm/templates/_helpers.tpl rename to runtime_k3d/src/app_deployment/config/helm/templates/_helpers.tpl diff --git a/runtime-k3d/src/app_deployment/config/helm/templates/vehicleapp.yaml b/runtime_k3d/src/app_deployment/config/helm/templates/vehicleapp.yaml similarity index 100% rename from runtime-k3d/src/app_deployment/config/helm/templates/vehicleapp.yaml rename to runtime_k3d/src/app_deployment/config/helm/templates/vehicleapp.yaml diff --git a/runtime-k3d/src/app_deployment/config/helm/values.yaml b/runtime_k3d/src/app_deployment/config/helm/values.yaml similarity index 100% rename from runtime-k3d/src/app_deployment/config/helm/values.yaml rename to runtime_k3d/src/app_deployment/config/helm/values.yaml diff --git a/runtime-k3d/src/app_deployment/config/podspec/vehicleapp.yaml b/runtime_k3d/src/app_deployment/config/podspec/vehicleapp.yaml similarity index 100% rename from runtime-k3d/src/app_deployment/config/podspec/vehicleapp.yaml rename to runtime_k3d/src/app_deployment/config/podspec/vehicleapp.yaml diff --git a/runtime-k3d/src/app_deployment/deploy_vehicleapp.py b/runtime_k3d/src/app_deployment/deploy_vehicleapp.py similarity index 98% rename from runtime-k3d/src/app_deployment/deploy_vehicleapp.py rename to runtime_k3d/src/app_deployment/deploy_vehicleapp.py index 1ecd0b22..b92b8191 100644 --- a/runtime-k3d/src/app_deployment/deploy_vehicleapp.py +++ b/runtime_k3d/src/app_deployment/deploy_vehicleapp.py @@ -16,8 +16,6 @@ from io import TextIOWrapper from build_vehicleapp import build_vehicleapp -from yaspin import yaspin - from velocitas_lib import ( create_log_file, get_app_manifest, @@ -28,6 +26,7 @@ is_docker_image_build_locally, push_docker_image_to_registry, ) +from yaspin import yaspin def is_vehicleapp_installed( @@ -106,7 +105,7 @@ def deploy_vehicleapp(): and display the progress using a given spinner.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("deploy-vapp", "runtime-k3d") + log_output = create_log_file("deploy-vapp", "runtime_k3d") with yaspin(text="Deploying VehicleApp...", color="cyan") as spinner: try: app_name = get_app_manifest()["name"].lower() diff --git a/runtime_k3d/src/requirements.txt b/runtime_k3d/src/requirements.txt new file mode 100644 index 00000000..d096d978 --- /dev/null +++ b/runtime_k3d/src/requirements.txt @@ -0,0 +1,3 @@ +yaspin==2.3.0 +ruamel.yaml==0.17.32 +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-kanto/__init__.py b/runtime_k3d/src/runtime/__init__.py similarity index 100% rename from runtime-kanto/__init__.py rename to runtime_k3d/src/runtime/__init__.py diff --git a/runtime-k3d/src/runtime/controlplane.py b/runtime_k3d/src/runtime/controlplane.py similarity index 99% rename from runtime-k3d/src/runtime/controlplane.py rename to runtime_k3d/src/runtime/controlplane.py index 83c6b85a..4224b569 100644 --- a/runtime-k3d/src/runtime/controlplane.py +++ b/runtime_k3d/src/runtime/controlplane.py @@ -18,10 +18,9 @@ from typing import List from deployment.lib import generate_nodeport -from yaspin.core import Yaspin - from velocitas_lib import get_package_path, require_env from velocitas_lib.services import get_services +from yaspin.core import Yaspin def registry_exists(log_output: TextIOWrapper | int = subprocess.DEVNULL) -> bool: @@ -284,7 +283,7 @@ def configure_controlplane( config_dir_path = os.path.join(get_package_path(), "config") dapr_config_dir_path = os.path.join( get_package_path(), - "runtime-k3d", + "runtime_k3d", "src", "runtime", "deployment", diff --git a/runtime-kanto/src/__init__.py b/runtime_k3d/src/runtime/deployment/__init__.py similarity index 100% rename from runtime-kanto/src/__init__.py rename to runtime_k3d/src/runtime/deployment/__init__.py diff --git a/runtime-k3d/src/runtime/deployment/config/.dapr/config.yaml b/runtime_k3d/src/runtime/deployment/config/.dapr/config.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/.dapr/config.yaml rename to runtime_k3d/src/runtime/deployment/config/.dapr/config.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/.helmignore b/runtime_k3d/src/runtime/deployment/config/helm/.helmignore similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/.helmignore rename to runtime_k3d/src/runtime/deployment/config/helm/.helmignore diff --git a/runtime-k3d/src/runtime/deployment/config/helm/Chart.yaml b/runtime_k3d/src/runtime/deployment/config/helm/Chart.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/Chart.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/Chart.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/_helpers.tpl b/runtime_k3d/src/runtime/deployment/config/helm/templates/_helpers.tpl similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/_helpers.tpl rename to runtime_k3d/src/runtime/deployment/config/helm/templates/_helpers.tpl diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/bash.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/bash.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/bash.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/bash.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/feedercan.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/feedercan.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/feedercan.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/feedercan.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/mockservice.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/mockservice.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/mockservice.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/mockservice.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/mqtt-broker.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/mqtt-broker.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/mqtt-broker.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/mqtt-broker.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/persistentVolume.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/persistentVolume.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/persistentVolume.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/persistentVolume.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/seatservice.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/seatservice.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/seatservice.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/seatservice.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/helm/templates/vehicledatabroker.yaml b/runtime_k3d/src/runtime/deployment/config/helm/templates/vehicledatabroker.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/helm/templates/vehicledatabroker.yaml rename to runtime_k3d/src/runtime/deployment/config/helm/templates/vehicledatabroker.yaml diff --git a/runtime-k3d/src/runtime/deployment/config/podspec/runtime_template.yaml b/runtime_k3d/src/runtime/deployment/config/podspec/runtime_template.yaml similarity index 100% rename from runtime-k3d/src/runtime/deployment/config/podspec/runtime_template.yaml rename to runtime_k3d/src/runtime/deployment/config/podspec/runtime_template.yaml diff --git a/runtime-k3d/src/runtime/deployment/gen_helm.py b/runtime_k3d/src/runtime/deployment/gen_helm.py similarity index 98% rename from runtime-k3d/src/runtime/deployment/gen_helm.py rename to runtime_k3d/src/runtime/deployment/gen_helm.py index 43207957..43f790d2 100644 --- a/runtime-k3d/src/runtime/deployment/gen_helm.py +++ b/runtime_k3d/src/runtime/deployment/gen_helm.py @@ -20,13 +20,11 @@ from typing import Any import ruamel.yaml as yaml - from velocitas_lib.services import Service, ServiceSpecConfig, get_services sys.path.append(os.path.join(os.path.dirname(__file__), "..", "deployment")) from lib import generate_nodeport # noqa: E402 - from velocitas_lib import get_package_path, get_workspace_dir # noqa: E402 @@ -98,7 +96,7 @@ def generate_values_file(output_path: str): def copy_helm_chart_and_templates(output_path: str): shutil.copytree( - f"{get_package_path()}/runtime-k3d/src/runtime/deployment/config/helm", + f"{get_package_path()}/runtime_k3d/src/runtime/deployment/config/helm", output_path, symlinks=False, ignore=None, diff --git a/runtime-k3d/src/runtime/deployment/gen_podspec.py b/runtime_k3d/src/runtime/deployment/gen_podspec.py similarity index 99% rename from runtime-k3d/src/runtime/deployment/gen_podspec.py rename to runtime_k3d/src/runtime/deployment/gen_podspec.py index 4559551f..90d6b040 100644 --- a/runtime-k3d/src/runtime/deployment/gen_podspec.py +++ b/runtime_k3d/src/runtime/deployment/gen_podspec.py @@ -18,7 +18,6 @@ from typing import Any, Tuple import ruamel.yaml as yaml - from velocitas_lib import get_script_path, get_workspace_dir # noqa: E402 from velocitas_lib.services import ServiceSpecConfig, get_services diff --git a/runtime-k3d/src/runtime/deployment/lib.py b/runtime_k3d/src/runtime/deployment/lib.py similarity index 100% rename from runtime-k3d/src/runtime/deployment/lib.py rename to runtime_k3d/src/runtime/deployment/lib.py diff --git a/runtime-k3d/src/runtime/runtime-down.py b/runtime_k3d/src/runtime/runtime-down.py similarity index 95% rename from runtime-k3d/src/runtime/runtime-down.py rename to runtime_k3d/src/runtime/runtime-down.py index c3957582..7cd4f4b6 100644 --- a/runtime-k3d/src/runtime/runtime-down.py +++ b/runtime_k3d/src/runtime/runtime-down.py @@ -14,16 +14,15 @@ from controlplane import reset_controlplane from runtime import undeploy_runtime -from yaspin import yaspin - from velocitas_lib import create_log_file +from yaspin import yaspin def runtime_down(): """Stop the K3D runtime.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("runtime-down", "runtime-k3d") + log_output = create_log_file("runtime-down", "runtime_k3d") with yaspin(text="Stopping k3d runtime...", color="cyan") as spinner: try: reset_controlplane(spinner, log_output) diff --git a/runtime-k3d/src/runtime/runtime-up.py b/runtime_k3d/src/runtime/runtime-up.py similarity index 96% rename from runtime-k3d/src/runtime/runtime-up.py rename to runtime_k3d/src/runtime/runtime-up.py index e3cfe296..40eb07be 100644 --- a/runtime-k3d/src/runtime/runtime-up.py +++ b/runtime_k3d/src/runtime/runtime-up.py @@ -16,16 +16,15 @@ from controlplane import configure_controlplane from runtime import deploy_runtime -from yaspin import yaspin - from velocitas_lib import create_log_file +from yaspin import yaspin def runtime_up(skip_services: bool): """Start up the K3D runtime.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("runtime-up", "runtime-k3d") + log_output = create_log_file("runtime-up", "runtime_k3d") with yaspin(text="Configuring controlplane for k3d...", color="cyan") as spinner: try: configure_controlplane(spinner, log_output) diff --git a/runtime-k3d/src/runtime/runtime.py b/runtime_k3d/src/runtime/runtime.py similarity index 99% rename from runtime-k3d/src/runtime/runtime.py rename to runtime_k3d/src/runtime/runtime.py index 4b3ef569..bc6ada7b 100644 --- a/runtime-k3d/src/runtime/runtime.py +++ b/runtime_k3d/src/runtime/runtime.py @@ -17,9 +17,8 @@ import sys from io import TextIOWrapper -from yaspin.core import Yaspin - from velocitas_lib.services import get_services +from yaspin.core import Yaspin sys.path.append(os.path.join(os.path.dirname(__file__), "..", "runtime")) from deployment.gen_helm import gen_helm # noqa: E402 diff --git a/runtime-k3d/test/.dapr/components/pubsub.yaml b/runtime_k3d/test/.dapr/components/pubsub.yaml similarity index 100% rename from runtime-k3d/test/.dapr/components/pubsub.yaml rename to runtime_k3d/test/.dapr/components/pubsub.yaml diff --git a/runtime-k3d/test/.dapr/config.yaml b/runtime_k3d/test/.dapr/config.yaml similarity index 100% rename from runtime-k3d/test/.dapr/config.yaml rename to runtime_k3d/test/.dapr/config.yaml diff --git a/runtime-k3d/test/.velocitas.json b/runtime_k3d/test/.velocitas.json similarity index 100% rename from runtime-k3d/test/.velocitas.json rename to runtime_k3d/test/.velocitas.json diff --git a/runtime-k3d/test/app/AppManifest.json b/runtime_k3d/test/app/AppManifest.json similarity index 100% rename from runtime-k3d/test/app/AppManifest.json rename to runtime_k3d/test/app/AppManifest.json diff --git a/runtime-k3d/test/app/Dockerfile b/runtime_k3d/test/app/Dockerfile similarity index 100% rename from runtime-k3d/test/app/Dockerfile rename to runtime_k3d/test/app/Dockerfile diff --git a/runtime-k3d/test/app/requirements-links.txt b/runtime_k3d/test/app/requirements-links.txt similarity index 100% rename from runtime-k3d/test/app/requirements-links.txt rename to runtime_k3d/test/app/requirements-links.txt diff --git a/runtime-k3d/test/app/requirements.txt b/runtime_k3d/test/app/requirements.txt similarity index 100% rename from runtime-k3d/test/app/requirements.txt rename to runtime_k3d/test/app/requirements.txt diff --git a/runtime-k3d/test/app/src/main.py b/runtime_k3d/test/app/src/main.py similarity index 100% rename from runtime-k3d/test/app/src/main.py rename to runtime_k3d/test/app/src/main.py diff --git a/runtime-k3d/test/integration/integration_test.py b/runtime_k3d/test/integration/integration_test.py similarity index 100% rename from runtime-k3d/test/integration/integration_test.py rename to runtime_k3d/test/integration/integration_test.py diff --git a/runtime-k3d/test/requirements.txt b/runtime_k3d/test/requirements.txt similarity index 59% rename from runtime-k3d/test/requirements.txt rename to runtime_k3d/test/requirements.txt index 6595eddd..f079860b 100644 --- a/runtime-k3d/test/requirements.txt +++ b/runtime_k3d/test/requirements.txt @@ -3,4 +3,4 @@ pytest-ordering==0.6 pytest-asyncio==0.20.3 pytest-cov==4.0.0 types-mock==4.0.15.2 -velocitas_lib +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-k3d/test/test_gen_helm.py b/runtime_k3d/test/test_gen_helm.py similarity index 99% rename from runtime-k3d/test/test_gen_helm.py rename to runtime_k3d/test/test_gen_helm.py index 79d3a7a7..2281a317 100644 --- a/runtime-k3d/test/test_gen_helm.py +++ b/runtime_k3d/test/test_gen_helm.py @@ -17,7 +17,6 @@ import sys import pytest - from velocitas_lib.services import ServiceSpecConfig sys.path.append(os.path.join(os.path.dirname(__file__), "..", "src/runtime")) diff --git a/runtime-k3d/test/test_gen_podspec.py b/runtime_k3d/test/test_gen_podspec.py similarity index 99% rename from runtime-k3d/test/test_gen_podspec.py rename to runtime_k3d/test/test_gen_podspec.py index a8b63363..60a01d5a 100644 --- a/runtime-k3d/test/test_gen_podspec.py +++ b/runtime_k3d/test/test_gen_podspec.py @@ -18,7 +18,6 @@ from typing import Optional import pytest - from velocitas_lib.services import ServiceSpecConfig sys.path.append(os.path.join(os.path.dirname(__file__), "..", "src/runtime")) diff --git a/runtime-k3d/test/test_lib.py b/runtime_k3d/test/test_lib.py similarity index 100% rename from runtime-k3d/test/test_lib.py rename to runtime_k3d/test/test_lib.py diff --git a/runtime-kanto/README.md b/runtime_kanto/README.md similarity index 100% rename from runtime-kanto/README.md rename to runtime_kanto/README.md diff --git a/runtime-kanto/src/app_deployment/__init__.py b/runtime_kanto/__init__.py similarity index 100% rename from runtime-kanto/src/app_deployment/__init__.py rename to runtime_kanto/__init__.py diff --git a/runtime-kanto/src/runtime/__init__.py b/runtime_kanto/src/__init__.py similarity index 100% rename from runtime-kanto/src/runtime/__init__.py rename to runtime_kanto/src/__init__.py diff --git a/runtime-local/__init__.py b/runtime_kanto/src/app_deployment/__init__.py similarity index 100% rename from runtime-local/__init__.py rename to runtime_kanto/src/app_deployment/__init__.py diff --git a/runtime-kanto/src/app_deployment/build_vehicleapp.py b/runtime_kanto/src/app_deployment/build_vehicleapp.py similarity index 95% rename from runtime-kanto/src/app_deployment/build_vehicleapp.py rename to runtime_kanto/src/app_deployment/build_vehicleapp.py index a91d6b41..721076f4 100644 --- a/runtime-kanto/src/app_deployment/build_vehicleapp.py +++ b/runtime_kanto/src/app_deployment/build_vehicleapp.py @@ -12,17 +12,16 @@ # # SPDX-License-Identifier: Apache-2.0 -from yaspin import yaspin - from velocitas_lib import create_log_file from velocitas_lib.docker import build_vehicleapp_image +from yaspin import yaspin def build_vehicleapp(): """Build VehicleApp docker image and display the progress using a spinner.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("build-vapp", "runtime-kanto") + log_output = create_log_file("build-vapp", "runtime_kanto") with yaspin(text="Building VehicleApp...", color="cyan") as spinner: try: status = "> Building VehicleApp image" diff --git a/runtime-kanto/src/app_deployment/deploy_vehicleapp.py b/runtime_kanto/src/app_deployment/deploy_vehicleapp.py similarity index 99% rename from runtime-kanto/src/app_deployment/deploy_vehicleapp.py rename to runtime_kanto/src/app_deployment/deploy_vehicleapp.py index 37d26e59..1f98146f 100644 --- a/runtime-kanto/src/app_deployment/deploy_vehicleapp.py +++ b/runtime_kanto/src/app_deployment/deploy_vehicleapp.py @@ -17,14 +17,13 @@ import sys from io import TextIOWrapper -from yaspin import yaspin - from velocitas_lib import create_log_file, get_app_manifest from velocitas_lib.docker import ( is_docker_image_build_locally, push_docker_image_to_registry, ) from velocitas_lib.services import get_service_port +from yaspin import yaspin sys.path.append(os.path.join(os.path.dirname(__file__), "..", "app_deployment")) from build_vehicleapp import build_vehicleapp # noqa: E402 @@ -220,7 +219,7 @@ def deploy_vehicleapp(): and display the progress using a given spinner.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("deploy-vapp", "runtime-kanto") + log_output = create_log_file("deploy-vapp", "runtime_kanto") with yaspin(text="Deploying VehicleApp...", color="cyan") as spinner: try: app_name = get_app_manifest()["name"].lower() diff --git a/runtime_kanto/src/requirements.txt b/runtime_kanto/src/requirements.txt new file mode 100644 index 00000000..c7b56db1 --- /dev/null +++ b/runtime_kanto/src/requirements.txt @@ -0,0 +1,2 @@ +yaspin==2.3.0 +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-local/src/__init__.py b/runtime_kanto/src/runtime/__init__.py similarity index 100% rename from runtime-local/src/__init__.py rename to runtime_kanto/src/runtime/__init__.py diff --git a/runtime-kanto/src/runtime/config.json b/runtime_kanto/src/runtime/config.json similarity index 100% rename from runtime-kanto/src/runtime/config.json rename to runtime_kanto/src/runtime/config.json diff --git a/runtime-kanto/src/runtime/controlplane_kanto.py b/runtime_kanto/src/runtime/controlplane_kanto.py similarity index 99% rename from runtime-kanto/src/runtime/controlplane_kanto.py rename to runtime_kanto/src/runtime/controlplane_kanto.py index 6e01fcbb..c6fc1111 100644 --- a/runtime-kanto/src/runtime/controlplane_kanto.py +++ b/runtime_kanto/src/runtime/controlplane_kanto.py @@ -15,9 +15,8 @@ import subprocess from io import TextIOWrapper -from yaspin.core import Yaspin - from velocitas_lib.docker import container_exists +from yaspin.core import Yaspin K3D_REGISTRY_NAME = "k3d-registry" KANTO_REGISTRY_NAME = "registry" diff --git a/runtime-kanto/src/runtime/deployment/databroker.json b/runtime_kanto/src/runtime/deployment/databroker.json similarity index 100% rename from runtime-kanto/src/runtime/deployment/databroker.json rename to runtime_kanto/src/runtime/deployment/databroker.json diff --git a/runtime-kanto/src/runtime/deployment/feedercan.json b/runtime_kanto/src/runtime/deployment/feedercan.json similarity index 100% rename from runtime-kanto/src/runtime/deployment/feedercan.json rename to runtime_kanto/src/runtime/deployment/feedercan.json diff --git a/runtime-kanto/src/runtime/deployment/mockservice.json b/runtime_kanto/src/runtime/deployment/mockservice.json similarity index 100% rename from runtime-kanto/src/runtime/deployment/mockservice.json rename to runtime_kanto/src/runtime/deployment/mockservice.json diff --git a/runtime-kanto/src/runtime/deployment/mosquitto.json b/runtime_kanto/src/runtime/deployment/mosquitto.json similarity index 100% rename from runtime-kanto/src/runtime/deployment/mosquitto.json rename to runtime_kanto/src/runtime/deployment/mosquitto.json diff --git a/runtime-kanto/src/runtime/deployment/seatservice.json b/runtime_kanto/src/runtime/deployment/seatservice.json similarity index 100% rename from runtime-kanto/src/runtime/deployment/seatservice.json rename to runtime_kanto/src/runtime/deployment/seatservice.json diff --git a/runtime-kanto/src/runtime/runtime_down.py b/runtime_kanto/src/runtime/runtime_down.py similarity index 92% rename from runtime-kanto/src/runtime/runtime_down.py rename to runtime_kanto/src/runtime/runtime_down.py index 65266edf..aff64d45 100644 --- a/runtime-kanto/src/runtime/runtime_down.py +++ b/runtime_kanto/src/runtime/runtime_down.py @@ -13,17 +13,17 @@ # SPDX-License-Identifier: Apache-2.0 from controlplane_kanto import reset_controlplane -from runtime_kanto import stop_kanto, undeploy_runtime +from velocitas_lib import create_log_file from yaspin import yaspin -from velocitas_lib import create_log_file +from .runtime_kanto import stop_kanto, undeploy_runtime def runtime_down(): """Stop the Kanto runtime.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("runtime-down", "runtime-kanto") + log_output = create_log_file("runtime-down", "runtime_kanto") with yaspin(text="Stopping Kanto...", color="cyan") as spinner: try: spinner.write("Removing containers...") diff --git a/runtime-kanto/src/runtime/runtime_kanto.py b/runtime_kanto/src/runtime/runtime_kanto.py similarity index 99% rename from runtime-kanto/src/runtime/runtime_kanto.py rename to runtime_kanto/src/runtime/runtime_kanto.py index 611a7d16..450d84bd 100644 --- a/runtime-kanto/src/runtime/runtime_kanto.py +++ b/runtime_kanto/src/runtime/runtime_kanto.py @@ -20,14 +20,13 @@ from io import TextIOWrapper from pathlib import Path -from yaspin.core import Yaspin - from velocitas_lib import ( get_app_manifest, get_package_path, get_script_path, get_workspace_dir, ) +from yaspin.core import Yaspin sys.path.append(os.path.join(os.path.dirname(__file__), "..", "app_deployment")) from deploy_vehicleapp import remove_vehicleapp # noqa: E402 @@ -184,7 +183,7 @@ def start_kanto(spinner: Yaspin, log_output: TextIOWrapper | int = subprocess.DE "--deployment-ctr-dir", f"{get_script_path()}/deployment", "--log-file", - f"{get_workspace_dir()}/logs/runtime-kanto/container-management.log", + f"{get_workspace_dir()}/logs/runtime_kanto/container-management.log", ], start_new_session=True, stderr=log_output, diff --git a/runtime-kanto/src/runtime/runtime_up.py b/runtime_kanto/src/runtime/runtime_up.py similarity index 93% rename from runtime-kanto/src/runtime/runtime_up.py rename to runtime_kanto/src/runtime/runtime_up.py index 9242324d..70cbb470 100644 --- a/runtime-kanto/src/runtime/runtime_up.py +++ b/runtime_kanto/src/runtime/runtime_up.py @@ -16,17 +16,17 @@ from controlplane_kanto import configure_controlplane from runtime_down import runtime_down -from runtime_kanto import is_kanto_running, start_kanto +from velocitas_lib import create_log_file from yaspin import yaspin -from velocitas_lib import create_log_file +from .runtime_kanto import is_kanto_running, start_kanto def runtime_up(): """Start up the K3D runtime.""" print("Hint: Log files can be found in your workspace's logs directory") - log_output = create_log_file("runtime-up", "runtime-kanto") + log_output = create_log_file("runtime-up", "runtime_kanto") with yaspin(text="Configuring controlplane for Kanto...", color="cyan") as spinner: try: configure_controlplane(spinner, log_output) diff --git a/runtime-kanto/test/.velocitas.json b/runtime_kanto/test/.velocitas.json similarity index 100% rename from runtime-kanto/test/.velocitas.json rename to runtime_kanto/test/.velocitas.json diff --git a/runtime-kanto/test/app/AppManifest.json b/runtime_kanto/test/app/AppManifest.json similarity index 100% rename from runtime-kanto/test/app/AppManifest.json rename to runtime_kanto/test/app/AppManifest.json diff --git a/runtime-kanto/test/app/Dockerfile b/runtime_kanto/test/app/Dockerfile similarity index 100% rename from runtime-kanto/test/app/Dockerfile rename to runtime_kanto/test/app/Dockerfile diff --git a/runtime-kanto/test/app/requirements-links.txt b/runtime_kanto/test/app/requirements-links.txt similarity index 100% rename from runtime-kanto/test/app/requirements-links.txt rename to runtime_kanto/test/app/requirements-links.txt diff --git a/runtime-kanto/test/app/requirements.txt b/runtime_kanto/test/app/requirements.txt similarity index 100% rename from runtime-kanto/test/app/requirements.txt rename to runtime_kanto/test/app/requirements.txt diff --git a/runtime-kanto/test/app/src/main.py b/runtime_kanto/test/app/src/main.py similarity index 100% rename from runtime-kanto/test/app/src/main.py rename to runtime_kanto/test/app/src/main.py diff --git a/runtime-kanto/test/integration/integration_test.py b/runtime_kanto/test/integration/integration_test.py similarity index 100% rename from runtime-kanto/test/integration/integration_test.py rename to runtime_kanto/test/integration/integration_test.py diff --git a/runtime-kanto/test/requirements.txt b/runtime_kanto/test/requirements.txt similarity index 100% rename from runtime-kanto/test/requirements.txt rename to runtime_kanto/test/requirements.txt diff --git a/runtime-local/README.md b/runtime_local/README.md similarity index 100% rename from runtime-local/README.md rename to runtime_local/README.md diff --git a/velocitas_lib/__init__.py b/runtime_local/__init__.py similarity index 100% rename from velocitas_lib/__init__.py rename to runtime_local/__init__.py diff --git a/velocitas_lib/src/velocitas_lib/middleware.py b/runtime_local/src/__init__.py similarity index 68% rename from velocitas_lib/src/velocitas_lib/middleware.py rename to runtime_local/src/__init__.py index cee9bcf7..6925ae78 100644 --- a/velocitas_lib/src/velocitas_lib/middleware.py +++ b/runtime_local/src/__init__.py @@ -11,17 +11,3 @@ # under the License. # # SPDX-License-Identifier: Apache-2.0 - -from enum import Enum - - -class MiddlewareType(Enum): - """Enumeration containing all possible middleware types.""" - - NATIVE = 0 - DAPR = 1 - - -def get_middleware_type() -> MiddlewareType: - """Return the current middleware type.""" - return MiddlewareType.DAPR diff --git a/runtime-local/src/ensure-dapr.sh b/runtime_local/src/ensure-dapr.sh similarity index 100% rename from runtime-local/src/ensure-dapr.sh rename to runtime_local/src/ensure-dapr.sh diff --git a/runtime-local/src/local_lib.py b/runtime_local/src/local_lib.py similarity index 98% rename from runtime-local/src/local_lib.py rename to runtime_local/src/local_lib.py index e21ef2b6..5bdee511 100644 --- a/runtime-local/src/local_lib.py +++ b/runtime_local/src/local_lib.py @@ -76,7 +76,7 @@ def run_service(service: Service) -> subprocess.Popen: Returns: The Popen object representing the root process running the required service """ - log = create_log_file(service.id, "runtime-local") + log = create_log_file(service.id, "runtime_local") log.write(f"Starting {service.id!r}\n") env_vars = dict[str, Optional[str]]() @@ -211,7 +211,7 @@ def stop_service(service: Service): Args: service (Service): The service to stop. """ - log = create_log_file(service.id, "runtime-local") + log = create_log_file(service.id, "runtime_local") log.write(f"Stopping {service.id!r}\n") if service.config.use_dapr and get_middleware_type() == MiddlewareType.DAPR: diff --git a/runtime_local/src/requirements.txt b/runtime_local/src/requirements.txt new file mode 100644 index 00000000..c7b56db1 --- /dev/null +++ b/runtime_local/src/requirements.txt @@ -0,0 +1,2 @@ +yaspin==2.3.0 +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-local/src/run-dapr-sidecar.py b/runtime_local/src/run-dapr-sidecar.py similarity index 100% rename from runtime-local/src/run-dapr-sidecar.py rename to runtime_local/src/run-dapr-sidecar.py diff --git a/runtime-local/src/run-vehicle-app.py b/runtime_local/src/run-vehicle-app.py similarity index 99% rename from runtime-local/src/run-vehicle-app.py rename to runtime_local/src/run-vehicle-app.py index 75ae1569..d0d56ed6 100644 --- a/runtime-local/src/run-vehicle-app.py +++ b/runtime_local/src/run-vehicle-app.py @@ -17,7 +17,6 @@ from typing import Optional from local_lib import MiddlewareType, get_dapr_sidecar_args, get_middleware_type - from velocitas_lib.services import get_services diff --git a/runtime-local/src/run-vehicledatabroker-cli.sh b/runtime_local/src/run-vehicledatabroker-cli.sh similarity index 100% rename from runtime-local/src/run-vehicledatabroker-cli.sh rename to runtime_local/src/run-vehicledatabroker-cli.sh diff --git a/runtime-local/src/run_service.py b/runtime_local/src/run_service.py similarity index 98% rename from runtime-local/src/run_service.py rename to runtime_local/src/run_service.py index 07f5e211..7c2fac84 100644 --- a/runtime-local/src/run_service.py +++ b/runtime_local/src/run_service.py @@ -20,10 +20,9 @@ from typing import Dict, Optional from local_lib import run_service, stop_container, stop_service -from yaspin import yaspin - from velocitas_lib import get_log_file_name from velocitas_lib.services import Service, get_services, get_specific_service +from yaspin import yaspin spawned_processes: Dict[str, subprocess.Popen] = {} @@ -42,7 +41,7 @@ def run_specific_service(service: Service) -> None: terminate_spawned_processes() print(f"Starting {service.id=} failed") with open( - get_log_file_name(service.id, "runtime-local"), + get_log_file_name(service.id, "runtime_local"), mode="r", encoding="utf-8", ) as log: diff --git a/runtime-local/src/runtime-up.py b/runtime_local/src/runtime-up.py similarity index 97% rename from runtime-local/src/runtime-up.py rename to runtime_local/src/runtime-up.py index b87922e2..990930c5 100644 --- a/runtime-local/src/runtime-up.py +++ b/runtime_local/src/runtime-up.py @@ -18,10 +18,9 @@ from typing import Dict from local_lib import run_service, stop_container, stop_service -from yaspin import yaspin - from velocitas_lib import get_log_file_name from velocitas_lib.services import get_services +from yaspin import yaspin spawned_processes: Dict[str, subprocess.Popen] = {} @@ -45,7 +44,7 @@ def run_services() -> None: terminate_spawned_processes() print(f"Starting {service.id=} failed") with open( - get_log_file_name(service.id, "runtime-local"), + get_log_file_name(service.id, "runtime_local"), mode="r", encoding="utf-8", ) as log: diff --git a/runtime-local/src/runtime/config/.dapr/components/pubsub.yaml b/runtime_local/src/runtime/config/.dapr/components/pubsub.yaml similarity index 100% rename from runtime-local/src/runtime/config/.dapr/components/pubsub.yaml rename to runtime_local/src/runtime/config/.dapr/components/pubsub.yaml diff --git a/runtime-local/src/runtime/config/.dapr/config.yaml b/runtime_local/src/runtime/config/.dapr/config.yaml similarity index 100% rename from runtime-local/src/runtime/config/.dapr/config.yaml rename to runtime_local/src/runtime/config/.dapr/config.yaml diff --git a/runtime-local/test/.velocitas.json b/runtime_local/test/.velocitas.json similarity index 100% rename from runtime-local/test/.velocitas.json rename to runtime_local/test/.velocitas.json diff --git a/runtime-local/test/integration/integration_test.py b/runtime_local/test/integration/integration_test.py similarity index 100% rename from runtime-local/test/integration/integration_test.py rename to runtime_local/test/integration/integration_test.py diff --git a/runtime_local/test/requirements.txt b/runtime_local/test/requirements.txt new file mode 100644 index 00000000..e92f8346 --- /dev/null +++ b/runtime_local/test/requirements.txt @@ -0,0 +1,2 @@ +pytest==7.2.1 +git+https://github.com/eclipse-velocitas/velocitas-lib.git@v0.0.2 diff --git a/runtime-local/test/test_run_service.py b/runtime_local/test/test_run_service.py similarity index 96% rename from runtime-local/test/test_run_service.py rename to runtime_local/test/test_run_service.py index 0578357b..c02dea9c 100644 --- a/runtime-local/test/test_run_service.py +++ b/runtime_local/test/test_run_service.py @@ -27,6 +27,7 @@ @pytest.fixture() def set_env_vars(): os.environ["runtimeFilePath"] = "./runtime.json" + os.environ["VELOCITAS_PACKAGE_DIR"] = "." os.environ["VELOCITAS_WORKSPACE_DIR"] = "." os.environ["VELOCITAS_CACHE_DATA"] = '{"vspec_file_path":""}' os.environ["mockFilePath"] = "mock.py" diff --git a/setup.cfg b/setup.cfg index f2d99c43..2bbc3779 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,6 +12,8 @@ check_untyped_defs = True install_types = False non_interactive = False namespace_packages = True +ignore_missing_imports = True + [pydocstyle] match = '(?!test_).*\.py' diff --git a/velocitas_lib/pyproject.toml b/velocitas_lib/pyproject.toml deleted file mode 100644 index 6ceaf70d..00000000 --- a/velocitas_lib/pyproject.toml +++ /dev/null @@ -1,7 +0,0 @@ -[project] -name = "velocitas_lib" -version = "0.0.1" - -[build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" diff --git a/velocitas_lib/src/velocitas_lib/__init__.py b/velocitas_lib/src/velocitas_lib/__init__.py deleted file mode 100644 index fb6b730c..00000000 --- a/velocitas_lib/src/velocitas_lib/__init__.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -import inspect -import json -import os -import sys -from io import TextIOWrapper -from pathlib import Path -from typing import Any, Dict - - -def require_env(name: str) -> str: - """Require and return an environment variable. - - Args: - name (str): The name of the variable. - - Raises: - ValueError: In case the environment variable is not set. - - Returns: - str: The value of the variable. - """ - var = os.getenv(name) - if not var: - raise ValueError(f"Environment variable {name!r} not set!") - return var - - -def get_workspace_dir() -> str: - """Return the workspace directory.""" - return require_env("VELOCITAS_WORKSPACE_DIR") - - -def get_app_manifest() -> dict: - return json.loads(require_env("VELOCITAS_APP_MANIFEST")) - - -def get_script_path() -> str: - """Return the absolute path to the directory the invoked Python script - is located in.""" - return os.path.dirname(os.path.realpath(sys.argv[0])) - - -def get_package_path() -> Path: - """Return the absolute path to the package directory the invoked Python - script belongs to.""" - invoking_file_path = inspect.stack()[1].filename - parents = Path(invoking_file_path).resolve().parents - for parent in parents: - if parent.is_dir() and "manifest.json" in os.listdir(parent): - return parent - - raise FileNotFoundError( - f"Unable to find the package path of '{invoking_file_path}'!" - ) - - -def get_cache_data() -> Dict[str, Any]: - """Return the data of the cache as Python object.""" - return json.loads(require_env("VELOCITAS_CACHE_DATA")) - - -def get_log_file_name(service_id: str, runtime_id: str) -> str: - """Build the log file name for the given service and runtime. - - Args: - service_id (str): The ID of the service to log. - runtime_id (str): The ID of the runtime to log. - - Returns: - str: The log file name. - """ - return os.path.join(get_workspace_dir(), "logs", runtime_id, f"{service_id}.log") - - -def create_log_file(service_id: str, runtime_id: str) -> TextIOWrapper: - """Create a log file for the given service and runtime. - - Args: - service_id (str): The ID of the service to log. - runtime_id (str): The ID of the runtime to log. - - Returns: - TextIOWrapper: The log file. - """ - log_file_name = get_log_file_name(service_id, runtime_id) - os.makedirs(os.path.dirname(log_file_name), exist_ok=True) - return open(log_file_name, "w", encoding="utf-8") diff --git a/velocitas_lib/src/velocitas_lib/docker.py b/velocitas_lib/src/velocitas_lib/docker.py deleted file mode 100644 index cb7f989d..00000000 --- a/velocitas_lib/src/velocitas_lib/docker.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -import os -import subprocess -from io import TextIOWrapper -from typing import List - -from velocitas_lib import get_app_manifest, get_workspace_dir, require_env - - -def build_vehicleapp_image(log_output: TextIOWrapper | int = subprocess.DEVNULL): - """Build VehicleApp docker image and display the progress using a spinner. - - Args: - log_output (TextIOWrapper | int): Logfile to write or DEVNULL by default. - """ - app_name = get_app_manifest()["name"].lower() - image_tag = f"localhost:12345/{app_name}:local" - dockerfile_path = require_env("dockerfilePath") - os.environ["DOCKER_BUILDKIT"] = "1" - - extra_proxy_args: List[str] = [ - "--build-arg", - "HTTP_PROXY", - "--build-arg", - "HTTPS_PROXY", - "--build-arg", - "FTP_PROXY", - "--build-arg", - "ALL_PROXY", - "--build-arg", - "NO_PROXY", - ] - - subprocess.check_call( - [ - "docker", - "build", - "-f", - dockerfile_path, - "--progress=plain", - "-t", - image_tag, - ] - + extra_proxy_args - + [ - ".", - "--no-cache", - ], - stdout=log_output, - stderr=log_output, - cwd=get_workspace_dir(), - ) - - -def is_docker_image_build_locally(app_name: str) -> bool: - """Check if vehicle app docker image is locally available - - Args: - app_name (str): App name to check for - """ - output = subprocess.check_output( - [ - "docker", - "images", - "-a", - f"localhost:12345/{app_name}:local", - "--format", - "{{.Repository}}:{{.Tag}}", - ], - ) - return output.decode("utf-8").strip() == f"localhost:12345/{app_name}:local" - - -def push_docker_image_to_registry( - app_name: str, log_output: TextIOWrapper | int = subprocess.DEVNULL -): - """Push docker image to local image registry - - Args: - app_name (str): App name to push to registry - log_output (TextIOWrapper | int): Logfile to write or DEVNULL by default. - """ - subprocess.check_call( - ["docker", "push", f"localhost:12345/{app_name}:local"], - stdout=log_output, - stderr=log_output, - ) - - -def container_exists( - name: str, log_output: TextIOWrapper | int = subprocess.DEVNULL -) -> bool: - """Check if a container with a given name exists. - - Args: - log_output (TextIOWrapper | int): Logfile to write or DEVNULL by default. - - Returns: - bool: True if the container exists, False if not. - """ - return "" != str( - subprocess.check_output( - ["docker", "ps", "-a", "-q", "-f", f"name={name}"], stderr=log_output - ), - "utf-8", - ) diff --git a/velocitas_lib/src/velocitas_lib/services.py b/velocitas_lib/src/velocitas_lib/services.py deleted file mode 100644 index d83dd6e8..00000000 --- a/velocitas_lib/src/velocitas_lib/services.py +++ /dev/null @@ -1,214 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -import json -import os -import re -from pathlib import Path -from typing import Dict, List, NamedTuple, Optional - -from velocitas_lib import get_package_path, get_workspace_dir, require_env -from velocitas_lib.variables import ProjectVariables - - -class ServiceSpecConfig(NamedTuple): - image: str - is_enabled: bool = True - env_vars: Dict[str, Optional[str]] = dict() - use_dapr: bool = True - args: List[str] = list() - ports: List[str] = list() - port_forwards: List[str] = list() - mounts: List[str] = list() - startup_log_patterns: List[str] = list() - - -class Service(NamedTuple): - id: str - config: ServiceSpecConfig - - -def resolve_functions(input_str: str) -> str: - while True: - input_str_match = re.search(r"\$(\w+)\((.*)\s*\)", input_str) - - if not input_str_match: - return input_str - - function_name = input_str_match.group(1).strip() - parameter = input_str_match.group(2).strip() - - return_value = None - if function_name == "pathInWorkspaceOrPackage": - path_in_workspace = os.path.join(get_workspace_dir(), parameter) - if os.path.isfile(path_in_workspace): - return_value = path_in_workspace - - if return_value is None: - path_in_package = os.path.join(get_package_path(), parameter) - if os.path.isfile(path_in_package): - return_value = path_in_package - - if return_value is None: - raise RuntimeError( - f"Path {parameter!r} not found in workspace or package!" - ) - else: - raise RuntimeError(f"Unsupported function: {function_name!r}!") - - match_span = input_str_match.span(0) - input_str = ( - input_str[0 : match_span[0]] + return_value + input_str[match_span[1] :] - ) - - -def parse_service_config( - service_id: str, service_spec_config: Dict -) -> ServiceSpecConfig: - """Parse service spec configuration and return it as an named tuple. - - Args: - service_id: The ID of the service to be parsed. - service_spec_config: The specificon of the services from config file. - """ - - is_enabled = True - use_dapr = True - container_image = None - env_vars = dict[str, Optional[str]]() - ports = [] - port_forwards = [] - mounts = [] - args = [] - patterns = [] - - variables = ProjectVariables() - - for config_entry in service_spec_config: - key = config_entry["key"] - value = config_entry["value"] - - if isinstance(value, str): - value = variables.replace_occurrences(value) - value = resolve_functions(value) - - if key == "enabled": - is_enabled = value is True or value == "true" - elif key == "image": - container_image = value - elif key == "env": - pair = value.split("=", 1) - inner_key = pair[0].strip() - env_vars[inner_key] = None - if len(pair) > 1: - env_vars[inner_key] = pair[1].strip() - elif key == "no-dapr": - if isinstance(value, str): - use_dapr = not value == "true" - elif isinstance(value, bool): - use_dapr = not value - else: - raise ValueError("Unsupported value type!") - elif key == "arg": - args.append(value) - elif key == "port": - ports.append(value) - elif key == "port-forward": - port_forwards.append(value) - elif key == "mount": - mounts.append(value) - elif key == "start-pattern": - patterns.append(value) - - if container_image is None: - raise KeyError(f"Service {service_id!r} does not provide an image!") - - return ServiceSpecConfig( - image=container_image, - is_enabled=is_enabled, - env_vars=env_vars, - use_dapr=use_dapr, - args=args, - ports=ports, - port_forwards=port_forwards, - mounts=mounts, - startup_log_patterns=patterns, - ) - - -def get_services(verbose: bool = True) -> List[Service]: - """Return all specified services as Python object.""" - path = Path(f"{get_package_path()}/runtime.json") - variable_value = require_env("runtimeFilePath") - - if variable_value is not None: - overwritten_path = Path(variable_value) - if not overwritten_path.is_absolute(): - overwritten_path = Path(get_workspace_dir()).joinpath(overwritten_path) - - if overwritten_path.exists(): - path = overwritten_path - - if verbose: - print(f"runtime.json path redirected to {path}") - - json_array: List[Dict] = json.load( - open( - path, - encoding="utf-8", - ) - ) - - services: List[Service] = list() - for service_json in json_array: - service_id = service_json["id"] - service_config = None - is_service_enabled = True - if "config" in service_json: - service_config = parse_service_config(service_id, service_json["config"]) - is_service_enabled = service_config.is_enabled - - if is_service_enabled: - if service_config is None: - raise KeyError(f"Service {service_id!r} does not have a config entry!") - - services.append(Service(service_id, service_config)) - - return services - - -def get_specific_service(service_id: str) -> Service: - """Return the specified service as Python object. - - Args: - service_id: The ID of the service to be parsed. - """ - services = get_services() - services = list(filter(lambda service: service.id == service_id, services)) - if len(services) == 0: - raise RuntimeError(f"Service with id '{service_id}' not defined") - if len(services) > 1: - raise RuntimeError( - f"Multiple service definitions of id '{service_id}' found, which to take?" - ) - return services[0] - - -def get_service_port(service_id: str) -> str: - """Return the service port as string for the specified service. - - Args: - service_id: The ID of the service to be parsed. - """ - return get_specific_service(service_id).config.ports[0] diff --git a/velocitas_lib/src/velocitas_lib/variables.py b/velocitas_lib/src/velocitas_lib/variables.py deleted file mode 100644 index f7812adf..00000000 --- a/velocitas_lib/src/velocitas_lib/variables.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -import os -import re -from typing import Dict - -from velocitas_lib import get_cache_data, get_package_path - - -def json_obj_to_flat_map(obj, prefix: str = "", separator: str = ".") -> Dict[str, str]: - """Flatten a JSON Object into a one dimensional dict by joining the keys - with the specified separator.""" - result = dict[str, str]() - if isinstance(obj, dict): - for key, value in obj.items(): - nested_key = f"{prefix}{separator}{key}" - result.update(json_obj_to_flat_map(value, nested_key, separator)) - elif isinstance(obj, list): - for index, value in enumerate(obj): - nested_key = f"{prefix}{separator}{index}" - result.update(json_obj_to_flat_map(value, nested_key, separator)) - else: - nested_key = f"{prefix}" - result[nested_key] = obj - - return result - - -class ProjectVariables: - def __init__(self, env: Dict[str, str] = os.environ): - self.__build_variables_map(env) - - def __build_variables_map(self, env: Dict[str, str]): - variables: Dict[str, str] = {} - variables.update(json_obj_to_flat_map(get_cache_data(), "builtin.cache")) - variables.update(env) - variables["builtin.package_dir"] = get_package_path() - self._variables = variables - - def replace_occurrences(self, input_str: str) -> str: - """Replace all occurrences of the defined variables in the input string""" - if "${{" not in input_str: - return input_str - input_str_match = re.search(r"(?<=\${{)(.*?)(?=}})", input_str) - if input_str_match: - input_str_value = input_str_match.group().strip() - if input_str_value not in self._variables: - raise KeyError(f"{input_str_value!r} not in {self._variables!r}") - for key, value in self._variables.items(): - input_str = input_str.replace("${{ " + key + " }}", str(value)) - return input_str - else: - raise ValueError(f"{input_str!r} not in the right format") diff --git a/velocitas_lib/test/requirements.txt b/velocitas_lib/test/requirements.txt deleted file mode 100644 index 770f6a40..00000000 --- a/velocitas_lib/test/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -pytest==7.2.1 -pytest-ordering==0.6 -pytest-asyncio==0.20.3 -pytest-cov==4.0.0 -types-mock==4.0.15.2 -pyfakefs==5.2.2 -velocitas_lib diff --git a/velocitas_lib/test/test_services.py b/velocitas_lib/test/test_services.py deleted file mode 100644 index 5bcd19b7..00000000 --- a/velocitas_lib/test/test_services.py +++ /dev/null @@ -1,31 +0,0 @@ -import os - -import pytest - -from velocitas_lib import get_package_path, get_workspace_dir -from velocitas_lib.services import resolve_functions - - -def test_resolve_functions__unknown_function__raises_exception(): - with pytest.raises(RuntimeError, match="Unsupported function: 'foo'!"): - resolve_functions("$foo( asd )") - - -def test_resolve_functions__pathInWorkspaceOrPackage__file_missing__raises_exception(): - with pytest.raises( - RuntimeError, match="Path 'asd' not found in workspace or package!" - ): - resolve_functions("$pathInWorkspaceOrPackage( asd )") - - -def test_resolve_functions__pathInWorkspaceOrPackage__file_exists_in_workspace(): - assert resolve_functions( - "$pathInWorkspaceOrPackage( manifest.json )" - ) == os.path.join(get_workspace_dir(), "manifest.json") - - -def test_resolve_functions__pathInWorkspaceOrPackage__file_exists_in_package(): - os.environ["VELOCITAS_WORKSPACE_DIR"] = ".." - assert resolve_functions( - "$pathInWorkspaceOrPackage( manifest.json )" - ) == os.path.join(get_package_path(), "manifest.json") diff --git a/velocitas_lib/test/test_variables.py b/velocitas_lib/test/test_variables.py deleted file mode 100644 index 0e09f6ca..00000000 --- a/velocitas_lib/test/test_variables.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -# flake8: noqa: U100 unused argument (because of pytest.fixture) - -import json -import os - -import pytest - -from velocitas_lib import get_cache_data, get_package_path -from velocitas_lib.variables import ProjectVariables, json_obj_to_flat_map - - -@pytest.fixture() -def set_test_env_var(): - os.environ["VELOCITAS_CACHE_DATA"] = '{"cache_key":"cache_value"}' - - -@pytest.fixture() -def set_velocitas_cache_data() -> str: - cache_data_mock = {"testPropA": "testValueA", "testPropB": "testValueB"} - os.environ["VELOCITAS_CACHE_DATA"] = json.dumps(cache_data_mock) - return os.environ["VELOCITAS_CACHE_DATA"] - - -def test_replace_occurrences__returns_correct_resolved_string(set_test_env_var): - input_str_a = "${{ test.string.a }}" - input_str_b = "/test/${{ test.string.b }}/test" - - variables_to_replace = { - "test.string.a": "testA", - "test.string.b": "testB", - } - - variables = ProjectVariables(variables_to_replace) - assert ( - variables.replace_occurrences(input_str_a) - == variables_to_replace["test.string.a"] - ) - assert ( - variables.replace_occurrences(input_str_b) - == f'/test/{variables_to_replace["test.string.b"]}/test' - ) - - -def test_replace_occurrences__variable_not_defined__raises_KeyError(set_test_env_var): - with pytest.raises(KeyError): - input_str_a = "${{ test.string.a }}" - variables_to_replace = { - "test.string.b": "testB", - } - ProjectVariables(variables_to_replace).replace_occurrences(input_str_a) - - -def test_replace_occurrences__no_replacement_in_input_str__returns_input_str( - set_test_env_var, -): - input_str_a = "test.string.a" - input_str_b = "/test/test.string.b/test" - input_str_c = "testImage:testVersion" - input_str_d = "url.com/owner/repo/service:version" - variables_to_replace = { - "test.string.a": "testA", - "test.string.b": "testB", - } - - variables = ProjectVariables(variables_to_replace) - assert variables.replace_occurrences(input_str_a) == input_str_a - assert variables.replace_occurrences(input_str_b) == input_str_b - assert variables.replace_occurrences(input_str_c) == input_str_c - assert variables.replace_occurrences(input_str_d) == input_str_d - - -def test_replace_occurrences__builtins_provided(set_test_env_var): - variables = ProjectVariables({}) - - assert ( - variables.replace_occurrences( - "This is the package path: '${{ builtin.package_dir }}'" - ) - == f"This is the package path: {get_package_path().__str__()!r}" - ) - - -def test_json_obj_to_flat_map__obj_is_dict__returns_replaced_cache_data_with_separator( - set_velocitas_cache_data, # type: ignore -): - separator = "test.separator" - cache_data_with_keys_to_replace = json_obj_to_flat_map(get_cache_data(), separator) - assert cache_data_with_keys_to_replace[f"{separator}.testPropA"] == "testValueA" - assert cache_data_with_keys_to_replace[f"{separator}.testPropB"] == "testValueB" - - -def test_json_obj_to_flat_map__obj_is_list__returns_replaced_cache_data_with_separator( - set_velocitas_cache_data, # type: ignore -): - separator = "test.separator" - cache_data_with_keys_to_replace = json_obj_to_flat_map( - list(get_cache_data()), separator - ) - assert cache_data_with_keys_to_replace[f"{separator}.0"] == "testPropA" - assert cache_data_with_keys_to_replace[f"{separator}.1"] == "testPropB" - - -def test_json_obj_to_flat_map__obj_is_str__returns_replaced_cache_data_with_separator( - set_velocitas_cache_data, # type: ignore -): - separator = "test.separator" - cache_data_with_keys_to_replace = json_obj_to_flat_map("test", separator) - assert cache_data_with_keys_to_replace[f"{separator}"] == "test" diff --git a/velocitas_lib/test/test_velocitas_lib.py b/velocitas_lib/test/test_velocitas_lib.py deleted file mode 100644 index 3da18343..00000000 --- a/velocitas_lib/test/test_velocitas_lib.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright (c) 2023 Robert Bosch GmbH -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -# flake8: noqa: U100 unused argument (because of pytest.fixture) - -import json -import os -import sys -from pathlib import Path - -import pytest -from pyfakefs.fake_filesystem import FakeFilesystem - -from velocitas_lib import ( - get_app_manifest, - get_cache_data, - get_package_path, - get_script_path, - get_workspace_dir, - require_env, -) -from velocitas_lib.services import get_services - - -@pytest.fixture() -def set_test_env_var() -> str: - os.environ["TEST"] = "test" - return os.environ["TEST"] - - -@pytest.fixture() -def set_velocitas_workspace_dir() -> str: - os.environ["VELOCITAS_WORKSPACE_DIR"] = "/test/vehicle-app-workspace" - return os.environ["VELOCITAS_WORKSPACE_DIR"] - - -@pytest.fixture() -def set_app_manifest() -> str: - app_manifest = {"vehicleModel": {"src": "test"}} - os.environ["VELOCITAS_APP_MANIFEST"] = json.dumps(app_manifest) - return os.environ["VELOCITAS_APP_MANIFEST"] - - -@pytest.fixture() -def set_velocitas_cache_data() -> str: - cache_data_mock = {"testPropA": "testValueA", "testPropB": "testValueB"} - os.environ["VELOCITAS_CACHE_DATA"] = json.dumps(cache_data_mock) - return os.environ["VELOCITAS_CACHE_DATA"] - - -@pytest.fixture() -def mock_filesystem(fs: FakeFilesystem) -> FakeFilesystem: - fs.add_real_file(os.path.join(Path(__file__).resolve().parents[2], "manifest.json")) - return fs - - -def test_require_env__env_var_set__returns_env_value(set_test_env_var): # type: ignore - assert require_env("TEST") == "test" - - -def test_require_env__env_var_not_set__raises_ValueError(): - with pytest.raises(ValueError): - require_env("TEST_ENV_NOT_SET") - - -def test_get_workspace_dir__returns_workspace_dir_path(set_velocitas_workspace_dir): # type: ignore - assert get_workspace_dir() == "/test/vehicle-app-workspace" - - -def test_get_app_manifest__app_manifest_set__returns_app_manifest_data( - set_app_manifest, -): - assert get_app_manifest()["vehicleModel"]["src"] == "test" - - -def test_get_app_manifest__missing_key__raises_KeyError(set_app_manifest): # type: ignore - with pytest.raises(KeyError): - get_app_manifest()["vehicleModel"]["srcs"] - - -def test_get_app_manifest__no_app_manifest__raises_ValueError(): - os.environ["VELOCITAS_APP_MANIFEST"] = "" - with pytest.raises(ValueError): - get_app_manifest() - - -def test_get_script_path__returns_script_path(): - assert get_script_path() == os.path.dirname(os.path.realpath(sys.argv[0])) - - -def test_get_package_path__returns_package_path(): - assert get_package_path() == Path(__file__).resolve().parents[2] - - -def test_get_cache_data__returns_cache_data(set_velocitas_cache_data): # type: ignore - assert get_cache_data()["testPropA"] == "testValueA" - assert get_cache_data()["testPropB"] == "testValueB" - - -def test_get_services__no_overwrite_provided__returns_default_services( - mock_filesystem: FakeFilesystem, -): - os.environ["runtimeFilePath"] = "runtime.json" - mock_filesystem.create_file( - f"{get_package_path()}/runtime.json", - contents='[ { "id": "service1", "config": [ { "key": "image", "value": "image-service1" } ] } ]', - ) - - all_services = get_services() - - assert len(all_services) == 1 - assert all_services[0].id == "service1" - assert all_services[0].config.image == "image-service1" - - -def test_get_services__overwrite_provided__returns_overwritten_services( - mock_filesystem: FakeFilesystem, -): - os.environ["runtimeFilePath"] = "runtime.json" - - mock_filesystem.create_file( - f"{get_package_path()}/runtime.json", - contents='[ { "id": "service1", "config": [ { "key": "image", "value": "image-service1" } ] } ]', - ) - mock_filesystem.create_file( - f"{get_workspace_dir()}/runtime.json", - contents='[ { "id": "my-custom-service", "config": [ { "key": "image", "value": "image-my-custom-service" } ] } ]', - ) - - all_services = get_services() - - assert len(all_services) == 1 - assert all_services[0].id == "my-custom-service" - assert all_services[0].config.image == "image-my-custom-service"