Skip to content

Commit

Permalink
fix(deployment): validates config trees while creating deployment
Browse files Browse the repository at this point in the history
Sometimes due to user error, incorrect parameter trees may be configured
while creating a deployment. This leads to cases where the paramsync
sidecar never starts in case of cloud deployments because the
initContainer never completes and the deployment get stuck.

This commit will fix that issue by validating the trees listed in the
manifest against the ones in the project.

Wrike Ticket: https://www.wrike.com/open.htm?id=1249775290
  • Loading branch information
pallabpain committed Jan 23, 2024
1 parent 324037c commit 8d688fc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 21 deletions.
41 changes: 29 additions & 12 deletions riocli/deployment/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@

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
from riocli.deployment.util import add_mount_volume_provision_config
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):
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand Down
12 changes: 3 additions & 9 deletions riocli/parameter/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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)
10 changes: 10 additions & 0 deletions riocli/parameter/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 8d688fc

Please sign in to comment.