diff --git a/riocli/deployment/model.py b/riocli/deployment/model.py index ebe0d0d9..df1355f2 100644 --- a/riocli/deployment/model.py +++ b/riocli/deployment/model.py @@ -16,18 +16,16 @@ import click from rapyuta_io import Client -from rapyuta_io.clients.catalog_client import Package from rapyuta_io.clients import ObjDict -from rapyuta_io.clients.static_route import StaticRoute +from rapyuta_io.clients.catalog_client import Package from rapyuta_io.clients.deployment import DeploymentNotRunningException, DeploymentPhaseConstants from rapyuta_io.clients.native_network import NativeNetwork -from rapyuta_io.clients.package import ProvisionConfiguration, RestartPolicy, \ - ExecutableMount -from rapyuta_io.clients.rosbag import ( - ROSBagJob, ROSBagOptions, ROSBagCompression, - UploadOptions, ROSBagOnDemandUploadOptions, ROSBagTimeRange, - ROSBagUploadTypes, OverrideOptions, TopicOverrideInfo) +from rapyuta_io.clients.package import ExecutableMount, ProvisionConfiguration, RestartPolicy +from rapyuta_io.clients.rosbag import (OverrideOptions, ROSBagCompression, ROSBagJob, ROSBagOnDemandUploadOptions, + ROSBagOptions, ROSBagTimeRange, ROSBagUploadTypes, TopicOverrideInfo, + UploadOptions) from rapyuta_io.clients.routed_network import RoutedNetwork +from rapyuta_io.clients.static_route import StaticRoute from riocli.constants import Colors from riocli.deployment.errors import ERRORS @@ -35,7 +33,9 @@ from riocli.jsonschema.validate import load_schema from riocli.model import Model from riocli.package.util import find_package_guid +from riocli.parameter.utils import list_trees from riocli.static_route.util import find_static_route_guid +from riocli.utils.cache import get_cache class Deployment(Model): @@ -194,9 +194,27 @@ def create_object(self, client: Client, **kwargs) -> typing.Any: if 'features' in self.spec: if 'params' in self.spec.features and self.spec.features.params.enabled: component_id = internal_component.componentId + disable_sync = self.spec.features.params.get('disableSync', False) + + # Validate trees in the manifest with the ones available + # to avoid misconfigurations. tree_names = self.spec.features.params.get('trees', []) - disable_sync = self.spec.features.params.get('disableSync', - False) + + # For multiple deployments in the same project, the list of + # available config trees is going to remain the same. Hence, + # we cache it once and keep fetching it from the cache. + cache_key = '{}-trees'.format(pkg.get('ownerProject')) + with get_cache() as c: + if c.get(cache_key) is None: + c.set(cache_key, set(list_trees())) + + available_trees = c.get(cache_key) + + if not available_trees: + raise ValueError("One or more trees are incorrect. Please run `rio parameter list` to confirm.") + + if not set(tree_names).issubset(available_trees): + raise ValueError("One or more trees are incorrect. Please run `rio parameter list` to confirm.") args = [] for e in executables: @@ -214,8 +232,7 @@ def create_object(self, client: Client, **kwargs) -> typing.Any: if component_id not in component_context: component_context[component_id] = {} - component_context[component_id][ - 'param_sync_exec_args'] = args + component_context[component_id]['param_sync_exec_args'] = args provision_config.set_component_alias(component_name, self.metadata.name) diff --git a/riocli/parameter/list.py b/riocli/parameter/list.py index 2995cdf5..9acb8f9d 100644 --- a/riocli/parameter/list.py +++ b/riocli/parameter/list.py @@ -13,10 +13,9 @@ # limitations under the License. import click from click_help_colors import HelpColorsCommand -from rapyuta_io.utils.rest_client import HttpMethod from riocli.constants import Colors -from riocli.parameter.utils import _api_call +from riocli.parameter.utils import list_trees from riocli.utils import tabulate_data @@ -31,14 +30,9 @@ def list_configuration_trees() -> None: List the Configuration Parameter Trees. """ try: - data = _api_call(HttpMethod.GET) - if 'data' not in data: - raise Exception('Failed to list configurations') - - trees = [[tree] for tree in data['data']] - + data = list_trees() + trees = [[tree] for tree in data] tabulate_data(trees, headers=['Tree Name']) - except Exception as e: click.secho(str(e), fg=Colors.RED) raise SystemExit(1) diff --git a/riocli/parameter/utils.py b/riocli/parameter/utils.py index 4ac41ee1..a706eb7b 100644 --- a/riocli/parameter/utils.py +++ b/riocli/parameter/utils.py @@ -17,10 +17,12 @@ import re import typing from filecmp import dircmp +from typing import List import click from directory_tree import display_tree from rapyuta_io.utils import RestClient +from rapyuta_io.utils.rest_client import HttpMethod from riocli.config import Configuration from riocli.constants import Colors @@ -84,6 +86,14 @@ def _api_call( return data +def list_trees() -> List[str]: + resp = _api_call(HttpMethod.GET) + if 'data' not in resp: + raise Exception('Failed to list configurations') + + return resp.get('data') + + class DeepDirCmp(dircmp): def phase3(self) -> None: