From 1048ff53dc96504676e1d2a91f4e32565880ad50 Mon Sep 17 00:00:00 2001 From: romill Date: Fri, 23 Feb 2024 18:03:43 +0530 Subject: [PATCH] feat(packages): uses v2 packages APIs --- examples/kiba-robots/03_packages.yaml | 3 +- .../apply/manifests/package-nonros-cloud.yaml | 4 +- .../manifests/package-nonros-device.yaml | 14 +- riocli/apply/manifests/package-ros-cloud.yaml | 4 +- .../package-ros-device-no-rosbag.yaml | 1 - .../manifests/package-ros-device-rosbag.yaml | 6 +- riocli/apply/manifests/package.yaml | 61 ++++++-- riocli/apply/resolver.py | 6 +- riocli/deployment/model.py | 10 -- riocli/jsonschema/schemas/package-schema.yaml | 44 +++--- riocli/package/delete.py | 22 +-- riocli/package/inspect.py | 66 +++++---- riocli/package/list.py | 30 ++-- riocli/package/model.py | 137 ++---------------- riocli/package/util.py | 13 +- riocli/v2client/client.py | 7 +- 16 files changed, 172 insertions(+), 256 deletions(-) diff --git a/examples/kiba-robots/03_packages.yaml b/examples/kiba-robots/03_packages.yaml index 206be437..f471f6e6 100644 --- a/examples/kiba-robots/03_packages.yaml +++ b/examples/kiba-robots/03_packages.yaml @@ -147,7 +147,8 @@ spec: executables: - type: docker name: django - command: /code/docker/entrypoint.sh + command: + - /code/docker/entrypoint.sh docker: image: rrdockerhub/sootballs_wcs:1.14.0-rc4 pullSecret: diff --git a/riocli/apply/manifests/package-nonros-cloud.yaml b/riocli/apply/manifests/package-nonros-cloud.yaml index 7b29f174..8d01abe0 100644 --- a/riocli/apply/manifests/package-nonros-cloud.yaml +++ b/riocli/apply/manifests/package-nonros-cloud.yaml @@ -4,7 +4,6 @@ metadata: name: "package-nonros-cloud" # Required version: "v1.0.0" # Required description: "A RIO non ROS cloud package" - project: "project-guid" labels: app: test spec: @@ -14,7 +13,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "sleep infinity" + command: + - "sleep infinity" runAsBash: True simulation: False limits: diff --git a/riocli/apply/manifests/package-nonros-device.yaml b/riocli/apply/manifests/package-nonros-device.yaml index ab63e04b..484b898e 100644 --- a/riocli/apply/manifests/package-nonros-device.yaml +++ b/riocli/apply/manifests/package-nonros-device.yaml @@ -4,7 +4,7 @@ metadata: name: "package-nonros-device" # Required version: "v1.0.0" # Required description: "A RIO non ROS device package" - project: "project-guid" + #project: "project-guid" labels: app: test spec: @@ -14,8 +14,9 @@ spec: restart: always # Options: [always, never, onfailure] executables: # Required - name: "exec-docker" - type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + type: preInstalled # Options: [docker (default), preInstalled] + command: + - "roslaunch talker talker.launch" runAsBash: True limits: # Optional cpu: 0.025 # Unit: Core (Optional) @@ -24,7 +25,7 @@ spec: httpGet: path: "/" port: 90 - initialDelaySeconds: 5 # Number of seconds after the container has started before liveness probes are initiated. + initialDelaySeconds: 50 # Number of seconds after the container has started before liveness probes are initiated. periodSeconds: 10 # How often (in seconds) to perform the probe. failureThreshold: 1 # Minimum consecutive failures for the probe to be considered failed after having succeeded. successThreshold: 3 # Minimum consecutive successes for the probe to be considered successful after having failed. @@ -39,8 +40,9 @@ spec: nameOrGUID: "secret-docker" - name: "exec-preInstalled" type: preInstalled # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" - environmentVars: + command: + - "roslaunch talker talker.launch" + environmentArgs: - name: "key1" # Required default: "key1-value" description: "A environment variable" diff --git a/riocli/apply/manifests/package-ros-cloud.yaml b/riocli/apply/manifests/package-ros-cloud.yaml index b852ee40..48f18e1a 100644 --- a/riocli/apply/manifests/package-ros-cloud.yaml +++ b/riocli/apply/manifests/package-ros-cloud.yaml @@ -4,7 +4,6 @@ metadata: name: "package-ros-cloud" # Required version: "v1.0.0" # Required description: "A RIO cloud ROS package" - project: "project-guid" labels: app: test spec: @@ -14,7 +13,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "roslaunch talker talker.launch" runAsBash: True simulation: False limits: diff --git a/riocli/apply/manifests/package-ros-device-no-rosbag.yaml b/riocli/apply/manifests/package-ros-device-no-rosbag.yaml index f0e894e2..9487ed32 100644 --- a/riocli/apply/manifests/package-ros-device-no-rosbag.yaml +++ b/riocli/apply/manifests/package-ros-device-no-rosbag.yaml @@ -5,7 +5,6 @@ metadata: name: "package-ros-device-no-rosbag" # Required version: "v1.0.0" # Required description: "A RIO device ROS package without rosbag" - project: "project-guid" labels: app: test spec: diff --git a/riocli/apply/manifests/package-ros-device-rosbag.yaml b/riocli/apply/manifests/package-ros-device-rosbag.yaml index 8c1eec66..445654c6 100644 --- a/riocli/apply/manifests/package-ros-device-rosbag.yaml +++ b/riocli/apply/manifests/package-ros-device-rosbag.yaml @@ -5,7 +5,6 @@ metadata: name: "package-ros-device-rosbag" # Required version: "v1.0.0" # Required description: "A RIO device ROS package with rosbag" - project: "project-guid" labels: app: test spec: @@ -16,7 +15,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "roslaunch talker talker.launch" runAsBash: True limits: # Optional cpu: 0.025 # Unit: Core (Optional) @@ -114,7 +114,7 @@ spec: - type: topic # Required, Options: [ topic, service, action ] name: "/telemetry" compression: False - scoped: False + scoped: True targeted: False qos: low # Options: [low, med, hi, max] - type: service # Required, Options: [ topic, service, action ] diff --git a/riocli/apply/manifests/package.yaml b/riocli/apply/manifests/package.yaml index aecaf737..55346c5a 100644 --- a/riocli/apply/manifests/package.yaml +++ b/riocli/apply/manifests/package.yaml @@ -4,7 +4,6 @@ metadata: name: "package-ros-cloud" # Required version: "v1.0.0" # Required description: "A RIO cloud ROS package" - project: "project-guid" labels: app: test spec: @@ -14,7 +13,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "roslaunch talker talker.launch" runAsBash: True simulation: False limits: @@ -138,7 +138,6 @@ metadata: name: "package-ros-device-rosbag" # Required version: "v1.0.0" # Required description: "A RIO device ROS package with rosbag" - project: "project-guid" labels: app: test spec: @@ -149,7 +148,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "shell-cmd" runAsBash: True limits: # Optional cpu: 0.025 # Unit: Core (Optional) @@ -268,7 +268,6 @@ metadata: name: "package-nonros-cloud" # Required version: "v1.0.0" # Required description: "A RIO non ROS cloud package" - project: "project-guid" labels: app: test spec: @@ -278,7 +277,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "sleep infinity" + command: + - "sleep infinity" runAsBash: True simulation: False limits: @@ -334,7 +334,6 @@ metadata: name: "package-nonros-device" # Required version: "v1.0.0" # Required description: "A RIO non ROS device package" - project: "project-guid" labels: app: test spec: @@ -345,7 +344,8 @@ spec: executables: # Required - name: "exec-docker-01" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "roslaunch talker talker.launch" runAsBash: True limits: # Optional cpu: 0.025 # Unit: Core (Optional) @@ -385,8 +385,9 @@ spec: imagePullPolicy: "Always" # Always, Never, IfNotPresent(default) - name: "exec-preInstalled" type: preInstalled # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" - environmentVars: + command: + - "roslaunch talker talker.launch" + environmentArgs: - name: "key1" # Required default: "key1-value" description: "A environment variable" @@ -403,7 +404,6 @@ metadata: name: "package-ros-device-no-rosbag" # Required version: "v1.0.0" # Required description: "A RIO device ROS package without rosbag" - project: "project-guid" labels: app: test spec: @@ -414,7 +414,8 @@ spec: executables: # Required - name: "exec-docker" type: docker # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" + command: + - "roslaunch talker talker.launch" runAsBash: True limits: cpu: 0.025 # Unit: Core (Optional) @@ -437,8 +438,9 @@ spec: nameOrGUID: "secret-docker" - name: "exec-preInstalled" type: preInstalled # Options: [docker (default), preInstalled] - command: "roslaunch talker talker.launch" - environmentVars: + command: + - "roslaunch talker talker.launch" + environmentArgs: - name: "key1" # Required default: "key1-value" description: "A environment variable" @@ -471,4 +473,33 @@ spec: compression: False scoped: False targeted: False - targeted: False \ No newline at end of file + targeted: False + +--- +apiVersion: "apiextensions.rapyuta.io/v1" +kind: "Package" +metadata: + name: "tc128-talker" # Required + version: "v1.0.0" # Required + description: "A RIO cloud ROS package" + labels: + app: test +spec: + runtime: cloud # Options: [device, cloud (default)] + cloud: + replicas: 1 # Required + executables: # Required + - name: "exec-build" + type: docker # Options: [docker (default), build, preInstalled] + command: + - "roslaunch talker talker.launch" + simulation: False + runAsBash: False + limits: + cpu: 0.025 # Unit: Core Options: [Multiple of 0.025, <= 8] + memory: 128 # Unit: MB Options: [Multiple of 128, <= 32768] + docker: + image: "quay.io/rapyuta/io_tutorials:latest" + ros: + enabled: True + version: melodic # Required, Options: [ kinetic, melodic, noetic ] diff --git a/riocli/apply/resolver.py b/riocli/apply/resolver.py index 17a7e912..91f0b546 100644 --- a/riocli/apply/resolver.py +++ b/riocli/apply/resolver.py @@ -118,7 +118,7 @@ def _guid_functor(self, kind): mapping = { 'secret': lambda x: munchify(x).metadata.guid, "project": lambda x: munchify(x).metadata.guid, - "package": lambda x: munchify(x)['id'], + "package": lambda x: munchify(x)['metadata']['guid'], "staticroute": lambda x: munchify(x)['metadata']['guid'], "deployment": lambda x: munchify(x)['deploymentId'], "network": lambda x: munchify(x)['metadata']['guid'], @@ -134,7 +134,7 @@ def _list_functors(self, kind): mapping = { 'secret': self.v2client.list_secrets, "project": self.v2client.list_projects, - "package": self.client.get_all_packages, + "package": self.v2client.list_packages, "staticroute": self.v2client.list_static_routes, "deployment": functools.partial(self.client.get_all_deployments, phases=[DeploymentPhaseConstants.SUCCEEDED, @@ -153,7 +153,7 @@ def _find_functors(self, kind): 'secret': lambda name, secrets: filter(lambda i: i.metadata.name == name, secrets), "project": lambda name, projects: filter(lambda i: i.metadata.name == name, projects), "package": lambda name, obj_list, version: filter( - lambda x: name == x.name and version == x['packageVersion'], obj_list), + lambda x: name == x.metadata.name and version == x.metadata.version, obj_list), "staticroute": lambda name, obj_list: filter( lambda x: name == x.metadata.name.rsplit('-', 1)[0], obj_list), "deployment": self._generate_find_guid_functor(), diff --git a/riocli/deployment/model.py b/riocli/deployment/model.py index 000495e3..df90a442 100644 --- a/riocli/deployment/model.py +++ b/riocli/deployment/model.py @@ -29,7 +29,6 @@ from riocli.deployment.util import add_mount_volume_provision_config, process_deployment_errors 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 @@ -271,15 +270,6 @@ def delete_object(self, client: Client, obj: typing.Any) -> typing.Any: def pre_process(cls, client: Client, d: typing.Dict) -> None: pass - def _get_package(self, client: Client) -> Package: - name = self.metadata.depends.nameOrGUID - if name.startswith('pkg-') or name.startswith('io-'): - guid = name - else: - guid = find_package_guid(client, name, self.metadata.depends.version) - - return client.get_package(package_id=guid) - def _get_provision_config(self, client: Client, pkg: Package): comp_name = pkg['plans']['components'][0]['name'] prov_config = pkg.get_provision_configuration() diff --git a/riocli/jsonschema/schemas/package-schema.yaml b/riocli/jsonschema/schemas/package-schema.yaml index 58e4f230..be4334f8 100644 --- a/riocli/jsonschema/schemas/package-schema.yaml +++ b/riocli/jsonschema/schemas/package-schema.yaml @@ -67,6 +67,7 @@ definitions: "$ref": "#/definitions/deviceComponentInfoSpec" executables: type: array + minItems: 1 items: "$ref": "#/definitions/deviceExecutableSpec" environmentArgs: @@ -88,6 +89,7 @@ definitions: executables: type: array + minItems: 1 items: "$ref": "#/definitions/cloudExecutableSpec" @@ -121,11 +123,11 @@ definitions: enum: - docker - preInstalled - command: - type: array - items: - type: string - description: Command to execute for the Exec probe. + command: + type: array + items: + type: string + description: Command to execute for the Exec probe. runAsBash: type: boolean default: True @@ -178,13 +180,13 @@ definitions: enum: - docker command: - type: string + type: array + items: + type: string + description: Command to execute for the Exec probe. runAsBash: type: boolean default: True - simulation: - type: boolean - default: False limits: type: object properties: @@ -413,6 +415,7 @@ definitions: - kinetic - melodic - noetic + - foxy default: melodic inboundScopedTargeted: type: boolean @@ -475,6 +478,15 @@ definitions: type: enum: - action + allOf: + - anyOf: + - not: + properties: + scoped: + const: true + targeted: + const: true + cloudROSBagJobSpec: type: object @@ -679,13 +691,8 @@ definitions: type: string secretDepends: properties: - kind: - const: secret - default: secret nameOrGUID: type: string - guid: - type: string diskDepends: properties: kind: @@ -766,11 +773,4 @@ definitions: type: integer default: 3 minimum: 1 - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. - oneOf: - - required: - - httpGet - - required: - - tcpSocket - - required: - - exec \ No newline at end of file + description: Minimum consecutive failures for the probe to be considered failed after having succeeded. \ No newline at end of file diff --git a/riocli/package/delete.py b/riocli/package/delete.py index 7cfe3390..7709fabd 100644 --- a/riocli/package/delete.py +++ b/riocli/package/delete.py @@ -14,15 +14,17 @@ from queue import Queue import click -from rapyuta_io.clients.package import Package +import functools from yaspin.api import Yaspin -from riocli.config import new_client +from riocli.config import new_v2_client from riocli.constants import Symbols, Colors from riocli.package.util import fetch_packages, print_packages_for_confirmation from riocli.utils import tabulate_data from riocli.utils.execute import apply_func_with_result from riocli.utils.spinner import with_spinner +from rapyuta_io import Client +from rapyuta_io.clients.package import Package @click.command('delete') @@ -46,7 +48,7 @@ def delete_package( """ Delete the package from the Platform """ - client = new_client() + client = new_v2_client() if not (package_name_or_regex or delete_all): spinner.text = "Nothing to delete" @@ -54,7 +56,7 @@ def delete_package( return try: - packages = fetch_packages(client, package_name_or_regex, delete_all, package_version) + packages = fetch_packages(client, package_name_or_regex, delete_all) except Exception as e: spinner.text = click.style( 'Failed to find package(s): {}'.format(e), Colors.RED) @@ -76,8 +78,9 @@ def delete_package( click.confirm('Do you want to delete the above package(s)?', default=True, abort=True) try: + f = functools.partial(_apply_delete, client) result = apply_func_with_result( - f=_apply_delete, items=packages, + f=f, items=packages, workers=workers, key=lambda x: x[0] ) @@ -107,11 +110,10 @@ def delete_package( spinner.red.fail(Symbols.ERROR) raise SystemExit(1) from e - -def _apply_delete(result: Queue, package: Package) -> None: - name_version = "{}@{}".format(package.packageName, package.packageVersion) +def _apply_delete(client: Client ,result: Queue, package: Package) -> None: + name_version = "{}@{}".format(package.metadata.name, package.metadata.version) try: - package.delete() + client.delete_package(package_name=package.metadata.name, query={"version": package.metadata.version}) result.put((name_version, True)) except Exception: - result.put((name_version, False)) + result.put((name_version, False)) \ No newline at end of file diff --git a/riocli/package/inspect.py b/riocli/package/inspect.py index 8d24efe7..63898ba6 100644 --- a/riocli/package/inspect.py +++ b/riocli/package/inspect.py @@ -12,12 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. import click -from rapyuta_io.clients.package import Package +from munch import unmunchify -from riocli.config import new_client -from riocli.package.util import name_to_guid +from riocli.config import new_v2_client from riocli.utils import inspect_with_format - +from riocli.utils.selector import show_selection @click.command('inspect') @click.option('--version', 'package_version', type=str, @@ -25,38 +24,41 @@ @click.option('--format', '-f', 'format_type', default='yaml', type=click.Choice(['json', 'yaml'], case_sensitive=False)) @click.argument('package-name') -@name_to_guid -def inspect_package(format_type: str, package_name: str, package_guid: str) -> None: +def inspect_package(format_type: str, package_name: str, package_version: str) -> None: """ Inspect the package resource """ try: - client = new_client() - package = client.get_package(package_guid) - data = make_package_inspectable(package) - inspect_with_format(data, format_type) + client = new_v2_client() + package_obj = None + if package_name.startswith("pkg-"): + packages = client.list_packages(query = {"guid": package_name}) + if packages: + package_obj = packages[0] + + elif package_name and package_version: + package_obj = client.get_package(package_name, query = {"version": package_version}) + elif package_name: + packages = client.list_packages(query={"name": package_name}) + + if len(packages) == 0: + click.secho("package not found", fg='red') + raise SystemExit(1) + + options = {} + package_objs = {} + for pkg in packages: + options[pkg.metadata.guid] = '{} ({})'.format(pkg.metadata.name, pkg.metadata.version) + package_objs[pkg.metadata.guid] = pkg + choice = show_selection(options, header='Following packages were found with the same name') + package_obj = package_objs[choice] + + if not package_obj: + click.secho("package not found", fg='red') + raise SystemExit(1) + + inspect_with_format(unmunchify(package_obj), format_type) + except Exception as e: click.secho(str(e), fg='red') raise SystemExit(1) - - -def make_package_inspectable(package: Package) -> dict: - return { - 'created_at': package.CreatedAt, - 'updated_at': package.UpdatedAt, - 'deleted_at': package.DeletedAt, - 'guid': package.guid, - 'package_version': package.packageVersion, - 'description': package.description, - 'package_name': package.packageName, - 'creator': package.creator, - 'owner_project': package.ownerProject, - 'tags': package.tags, - 'plans': package.plans, - 'status': package.status, - 'is_public': package.isPublic, - 'category': package.category, - 'bindable': package.bindable, - 'api_version': package.apiVersion, - 'package_id': package.packageId, - } diff --git a/riocli/package/list.py b/riocli/package/list.py index d0875418..3ccea526 100644 --- a/riocli/package/list.py +++ b/riocli/package/list.py @@ -16,10 +16,9 @@ import click from rapyuta_io.clients.package import Package -from riocli.config import new_client +from riocli.config import new_v2_client from riocli.utils import tabulate_data - @click.command('list') @click.option('--filter', 'filter_word', type=str, default=None, help='A sub-string can be provided to filter down the package list') @@ -28,16 +27,16 @@ def list_packages(filter_word: str) -> None: List the packages in the selected project """ try: - client = new_client() - packages = client.get_all_packages(name=filter_word) - _display_package_list(packages, show_header=True) + client = new_v2_client(with_project=True) + packages = client.list_packages() + _display_package_list(packages, filter_word,show_header=True) except Exception as e: click.secho(str(e), fg='red') raise SystemExit(1) - def _display_package_list( packages: typing.List[Package], + filter_word: str, show_header: bool = True, truncate_limit: int = 48, ) -> None: @@ -46,26 +45,31 @@ def _display_package_list( headers = ('Name', 'Version', 'Package ID', 'Description') # Show IO Packages first - iter_pkg = list(map(lambda x: x.packageName, packages)) + iter_pkg = list(map(lambda x: x.metadata.name, packages)) iter_pkg.sort() package_dict = {} for pkgName in iter_pkg: - filtered_pkg = list(filter(lambda x: x.packageName == pkgName, packages)) - filtered_pkg.sort(key=lambda x: x.packageVersion) + filtered_pkg = list(filter(lambda x: x.metadata.name == pkgName, packages)) + filtered_pkg.sort(key=lambda x: x.metadata.version) package_dict[pkgName] = filtered_pkg data = [] for pkgName, pkgVersionList in package_dict.items(): for package in pkgVersionList: - description = package.description - name = package.packageName + description = package.metadata.get("description", "") + name = package.metadata.name + + # check if filter word was passed. + # if filter word was passed and it is not present in package name then continue + if filter_word and not package.metadata.name.find(filter_word): + continue + if truncate_limit: if len(description) > truncate_limit: description = description[:truncate_limit] + '..' if len(name) > truncate_limit: name = name[:truncate_limit] + '..' - data.append([name, package.packageVersion, package.packageId, description]) - + data.append([name, package.metadata.version, package.metadata.guid, description]) tabulate_data(data, headers=headers) diff --git a/riocli/package/model.py b/riocli/package/model.py index c802ed68..5c8cb3c1 100644 --- a/riocli/package/model.py +++ b/riocli/package/model.py @@ -14,13 +14,14 @@ import os import typing -from munch import munchify +from munch import munchify, unmunchify + from rapyuta_io import Client from rapyuta_io.clients.package import RestartPolicy from riocli.jsonschema.validate import load_schema from riocli.model import Model - +from riocli.config import new_v2_client class Package(Model): RESTART_POLICY = { @@ -40,132 +41,23 @@ def find_object(self, client: Client): return obj - def create_object(self, client: Client, **kwargs): - pkg_object = munchify({ - 'name': 'default', - 'packageVersion': 'v1.0.0', - 'apiVersion': "2.1.0", - 'description': '', - 'bindable': True, - 'plans': [ - { - "inboundROSInterfaces": { - "anyIncomingScopedOrTargetedRosConfig": False - }, - 'singleton': False, - 'metadata': {}, - 'name': 'default', - 'dependentDeployments': [], - 'exposedParameters': [], - 'includePackages': [], - 'components': [ - ] - } - ], - }) - component_obj = munchify({ - 'requiredRuntime': 'cloud', - 'architecture': 'amd64', - 'executables': [], - 'parameters': [], - 'ros': {'services': [], 'topics': [], 'isROS': False, 'actions': []}, - 'exposedParameters': [], - 'includePackages': [], - 'rosBagJobDefs': [] - }) + def create_object(self, client: Client, **kwargs) -> typing.Any: + client = new_v2_client() - # metadata - # ✓ name, ✓ description, ✓ version - - pkg_object.name = self.metadata.name - pkg_object.packageVersion = self.metadata.version - - if 'description' in self.metadata: - pkg_object.description = self.metadata.description - - # spec - # executables - component_obj.name = 'default' # self.metadata.name #package == component in the single component model - - # TODO validate transform. specially nested secret. - component_obj.executables = list(map(self._map_executable, self.spec.executables)) - for exec in component_obj.executables: - if hasattr(exec, 'cmd') is False: - setattr(exec, 'cmd', []) - component_obj.requiredRuntime = self.spec.runtime - - # ✓ parameters - # TODO validate transform. - if 'environmentVars' in self.spec: - fixed_default = [] - for envVar in self.spec.environmentVars: - obj = envVar.copy() - if 'defaultValue' in obj: - obj['default'] = obj['defaultValue'] - del obj['default'] - - fixed_default.append(obj) - component_obj.parameters = fixed_default - # handle exposed params - exposed_parameters = [] - for entry in filter(lambda x: 'exposed' in x and x.exposed, self.spec.environmentVars): - if os.environ.get('DEBUG'): - print(entry.name) - exposed_parameters.append( - {'component': component_obj.name, 'param': entry.name, 'targetParam': entry.exposedName}) - pkg_object.plans[0].exposedParameters = exposed_parameters - - # device - # ✓ arch, ✓ restart - if self.spec.runtime == 'device': - component_obj.required_runtime = 'device' - component_obj.architecture = self.spec.device.arch - if 'restart' in self.spec.device: - component_obj.restart_policy = self.RESTART_POLICY[self.spec.device.restart.lower()] - - # cloud - # ✓ replicas - # ✓ endpoints - if 'cloud' in self.spec: - component_obj.cloudInfra = munchify(dict()) - if 'replicas' in self.spec.cloud: - component_obj.cloudInfra.replicas = self.spec.cloud.replicas - else: - component_obj.cloudInfra.replicas = 1 - - if 'endpoints' in self.spec: - endpoints = list(map(self._map_endpoints, self.spec.endpoints)) - component_obj.cloudInfra.endpoints = endpoints - - # ros: - # ✓ isros - # ✓ topic - # ✓ service - # ✓ action - # rosbagjob - if 'ros' in self.spec and self.spec.ros.enabled: - component_obj.ros.isROS = True - component_obj.ros.ros_distro = self.spec.ros.version - pkg_object.plans[0].inboundROSInterfaces = munchify({}) - - pkg_object.plans[ - 0].inboundROSInterfaces.anyIncomingScopedOrTargetedRosConfig = self.spec.ros.inboundScopedTargeted if 'inboundScopedTargeted' in self.spec.ros else False - if 'rosEndpoints' in self.spec.ros: - component_obj.ros.topics = list(self._get_rosendpoint_struct(self.spec.ros.rosEndpoints, 'topic')) - component_obj.ros.services = list(self._get_rosendpoint_struct(self.spec.ros.rosEndpoints, 'service')) - component_obj.ros.actions = list(self._get_rosendpoint_struct(self.spec.ros.rosEndpoints, 'action')) - - if 'rosBagJobs' in self.spec: - component_obj.rosBagJobDefs = self.spec.rosBagJobs - - pkg_object.plans[0].components = [component_obj] - return client.create_package(pkg_object) + # convert to a dict and remove the ResolverCache + # field since it's not JSON serializable + package = unmunchify(self) + package.pop("rc", None) + r = client.create_package(package) + return unmunchify(r) def update_object(self, client: Client, obj: typing.Any) -> typing.Any: + pass def delete_object(self, client: Client, obj: typing.Any) -> typing.Any: - client.delete_package(obj.packageId) + client = new_v2_client() + client.delete_package(obj.metadata.name, query={"version": obj.metadata.version}) def to_v1(self): # return v1Project(self.metadata.name) @@ -183,7 +75,6 @@ def _get_rosendpoint_struct(self, rosEndpoints, filter_type): return return_list def _map_executable(self, exec): - exec_object = munchify({ "name": exec.name, "simulationOptions": { diff --git a/riocli/package/util.py b/riocli/package/util.py index f218943a..fc939353 100644 --- a/riocli/package/util.py +++ b/riocli/package/util.py @@ -81,20 +81,16 @@ def fetch_packages( client: Client, package_name_or_regex: str, include_all: bool, - version: str = None ) -> List[Package]: - packages = client.get_all_packages(version=version) + packages = client.list_packages() result = [] for pkg in packages: # We cannot delete public packages. Skip them instead. - if 'io-public' in pkg.packageId: + if 'io-public' in pkg.metadata.guid: continue - if (include_all or package_name_or_regex == pkg.packageName or - pkg.packageId == package_name_or_regex or - (package_name_or_regex not in pkg.packageName and - re.search(r'^{}$'.format(package_name_or_regex), pkg.packageName))): + if include_all or re.search(package_name_or_regex, pkg.metadata.name): result.append(pkg) return result @@ -102,6 +98,5 @@ def fetch_packages( def print_packages_for_confirmation(packages: List[Package]) -> None: headers = ['Name', 'Version'] - data = [[p.packageName, p.packageVersion] for p in packages] - + data = [[p.metadata.name, p.metadata.version] for p in packages] tabulate_data(data, headers) diff --git a/riocli/v2client/client.py b/riocli/v2client/client.py index 91e1b6b6..aee7efc1 100644 --- a/riocli/v2client/client.py +++ b/riocli/v2client/client.py @@ -915,8 +915,6 @@ def delete_network(self, network_name: str, return munchify(data) - return munchify(data) - def list_deployments( self, @@ -950,7 +948,7 @@ def list_deployments( result.append(deployment['metadata']) return munchify(result) - + def create_deployment(self, deployment: dict) -> Munch: """ Create a new deployment @@ -968,7 +966,7 @@ def create_deployment(self, deployment: dict) -> Munch: raise Exception("deployment: {}".format(err_msg)) return munchify(data) - + def get_deployment( self, name: str, @@ -1019,6 +1017,7 @@ def delete_deployment(self, name: str, query: dict = None) -> Munch: params.update(query or {}) response = RestClient(url).method( HttpMethod.DELETE).headers(headers).execute() + handle_server_errors(response) data = json.loads(response.text) if not response.ok: