diff --git a/docs/schema/cloud.rst b/docs/schema/cloud.rst new file mode 100644 index 00000000..6981e242 --- /dev/null +++ b/docs/schema/cloud.rst @@ -0,0 +1,19 @@ +.. _cloud_schema: + +Schema: cloud +============== + +This document shows the schema of cloud build YAML files +supported by this library, in `JSON schema`_ format. +These files may be used within the ``CLOUD_IMAGES`` directory within +a :ref:`staging_structure`. + +The latest version of this schema is available in raw form at +https://release-engineering.github.io/pushsource/cloud-schema.yaml. + + +.. include:: ../../src/pushsource/_impl/schema/cloud-schema.yaml + :code: yaml + + +.. _JSON schema: https://json-schema.org/ diff --git a/docs/sources/staged.rst b/docs/sources/staged.rst index 168e44bf..adfdf15d 100644 --- a/docs/sources/staged.rst +++ b/docs/sources/staged.rst @@ -55,6 +55,7 @@ Here is a brief overview of the structure of a staging directory: root/destination/MODULEMD/* root/destination/RPMS/*.rpm root/destination/AWS_IMAGES/* + root/destination/CLOUD_IMAGES/* root/destination/RAW/* The staging directory consists of: @@ -196,6 +197,21 @@ Files in this directory must have metadata included in ``staged.yaml``. Will yield instances of :class:`~pushsource.AmiPushItem`. +root/destination/CLOUD_IMAGES/\* +................................ + +Each directory within ``CLOUD_IMAGES`` should contain one or more VMI(s) plus a +``resources.yaml`` . + +The ``resources.yaml`` contains all the information needed for the +images in that folder. + +:ref:`cloud_schema` provides a complete reference of the fields which can be set by this +file. + +Will yield instances of either :class:`~pushsource.AmiPushItem` or +:class:`~pushsource.VHDPushItem`. + root/destination/RAW/\* ....................... diff --git a/src/pushsource/_impl/backend/staged/staged_base.py b/src/pushsource/_impl/backend/staged/staged_base.py index 3e824ebe..1ec752a8 100644 --- a/src/pushsource/_impl/backend/staged/staged_base.py +++ b/src/pushsource/_impl/backend/staged/staged_base.py @@ -10,11 +10,12 @@ class TypeHandler(object): # Decorator for handling specific file directories (e.g. "FILES", "ISOS" etc) HANDLERS = {} - def __init__(self, type_name): + def __init__(self, type_name, accepts=lambda entry: entry.is_file()): self.type_name = type_name + self.accepts = accepts def __call__(self, fn): - TypeHandler.HANDLERS[self.type_name] = fn + TypeHandler.HANDLERS[self.type_name] = (fn, self.accepts) return fn @@ -29,19 +30,19 @@ def __init__(self, *args, **kwargs): super(StagedBaseMixin, self).__init__(*args, **kwargs) self._FILE_TYPES = self._FILE_TYPES.copy() for typename in TypeHandler.HANDLERS: - fn = TypeHandler.HANDLERS[typename] + fn, accepts = TypeHandler.HANDLERS[typename] bound_fn = partial(fn, self) self._FILE_TYPES[typename] = partial( - self.__mixin_push_items, delegate=bound_fn + self.__mixin_push_items, delegate=bound_fn, accepts=accepts ) - def __mixin_push_items(self, leafdir, metadata, delegate): + def __mixin_push_items(self, leafdir, metadata, delegate, accepts): out = [] LOG.debug("Looking for files in %s", leafdir) for entry in scandir(leafdir.path): - if entry.is_file(): + if accepts(entry): item = delegate(leafdir, metadata, entry) if item: out.append(item) diff --git a/src/pushsource/_impl/backend/staged/staged_cloud.py b/src/pushsource/_impl/backend/staged/staged_cloud.py new file mode 100644 index 00000000..e3b6ef81 --- /dev/null +++ b/src/pushsource/_impl/backend/staged/staged_cloud.py @@ -0,0 +1,161 @@ +import logging +import os +import yaml + +from datetime import datetime, timezone + +from .staged_base import StagedBaseMixin, handles_type +from ...model import ( + VHDPushItem, + VMIRelease, + AmiPushItem, + AmiRelease, + BootMode, + KojiBuildInfo, +) + +LOG = logging.getLogger("pushsource") + + +class StagedCloudMixin(StagedBaseMixin): + def __get_product_name(self, base_name): + splitted_name = base_name.split("-") + if len(splitted_name) > 1: + product = "-".join(splitted_name[:-1]) + else: + product = splitted_name[0] + return product + + def __build_ami_push_item(self, resources, origin, image, dest): + build_resources = resources.get("build") + release_resources = resources.get("release") or {} + name = image.get("path") + src = os.path.join(origin, name) + build_info = KojiBuildInfo( + name=build_resources.get("name"), + version=build_resources.get("version"), + release=build_resources.get("respin"), + ) + image_kwargs = { + "name": name, + "src": src, + "build_info": build_info, + "origin": origin, + "dest": [dest], + "sha256sum": image.get("sha256sum"), + } + + image_kwargs.update( + { + "boot_mode": ( + BootMode(resources.get("boot_mode")) + if resources.get("boot_mode") + else None + ) + } + ) + + release_kwargs = { + "product": self.__get_product_name(build_resources.get("name")), + "date": datetime.now(timezone.utc).strftime("%Y%m%d"), + "arch": image.get("architecture"), + "respin": int(build_resources.get("respin")) or 0, + } + release_attrs = [ + "version", + "base_product", + "base_version", + "variant", + "type", + ] + for key in release_attrs: + release_kwargs[key] = release_resources.get(key) + + image_kwargs["release"] = AmiRelease(**release_kwargs) + + image_attrs = [ + "type", + "region", + "virtualization", + "volume", + "root_device", + "description", + "sriov_net_support", + "ena_support", + "uefi_support", + "public_image", + "release_notes", + "usage_instructions", + "recommended_instance_type", + "marketplace_entity_type", + "image_id", + "scanning_port", + "user_name", + "version_title", + "security_groups", + "access_endpoint_url", + ] + + for key in image_attrs: + if key in resources: + image_kwargs[key] = resources.get(key) + + return AmiPushItem(**image_kwargs) + + def __build_azure_push_item(self, resources, origin, image, dest): + build_resources = resources.get("build") + name = image.get("path") + src = os.path.join(origin, name) + build_info = KojiBuildInfo( + name=build_resources.get("name"), + version=build_resources.get("version"), + release=build_resources.get("respin"), + ) + + release_kwargs = { + "product": self.__get_product_name(build_resources.get("name")), + "date": datetime.now(timezone.utc).strftime("%Y%m%d"), + "arch": image.get("architecture"), + "respin": int(build_resources.get("respin")) or 0, + } + + image_kwargs = { + "name": name, + "src": src, + "description": resources.get("description"), + "build_info": build_info, + "origin": origin, + "dest": [dest], + "sha256sum": image.get("sha256sum"), + "release": VMIRelease(**release_kwargs), + } + return VHDPushItem(**image_kwargs) + + @handles_type( + "CLOUD_IMAGES", + accepts=lambda entry: entry.is_dir() + and os.path.exists(os.path.join(entry.path, "resources.yaml")), + ) + def __cloud_push_item(self, leafdir, _, entry): + yaml_path = os.path.join(entry.path, "resources.yaml") + with open(yaml_path, "rt") as fh: + raw = yaml.safe_load(fh) + if not raw: + LOG.warning("Resources.yaml file at %s is empty (ignored)", yaml_path) + return + image_type = raw.get("type") or "" + images_info = raw.get("images") or [] + out = [] + for image in images_info: + if "/" in image.get("path"): + LOG.warning("Unexpected '/' in %s (ignored)", image.get("path")) + return + if image_type == "AMI": + out.append( + self.__build_ami_push_item(raw, entry.path, image, leafdir.dest) + ) + elif image_type == "VHD": + out.append( + self.__build_azure_push_item(raw, entry.path, image, leafdir.dest) + ) + return out diff --git a/src/pushsource/_impl/backend/staged/staged_source.py b/src/pushsource/_impl/backend/staged/staged_source.py index 300bfdfe..baed3493 100644 --- a/src/pushsource/_impl/backend/staged/staged_source.py +++ b/src/pushsource/_impl/backend/staged/staged_source.py @@ -16,6 +16,7 @@ from .staged_utils import StagingMetadata, StagingLeafDir from .staged_ami import StagedAmiMixin +from .staged_cloud import StagedCloudMixin from .staged_files import StagedFilesMixin from .staged_errata import StagedErrataMixin from .staged_compsxml import StagedCompsXmlMixin @@ -33,6 +34,7 @@ class StagedSource( Source, StagedAmiMixin, + StagedCloudMixin, StagedFilesMixin, StagedErrataMixin, StagedCompsXmlMixin, @@ -179,7 +181,11 @@ def _push_items_for_topdir(self, topdir): ) for f in completed_fs: for pushitem in f.result(): - yield pushitem + if isinstance(pushitem, list): + for p in pushitem: + yield p + else: + yield pushitem Source.register_backend("staged", StagedSource) diff --git a/src/pushsource/_impl/schema/cloud-schema.yaml b/src/pushsource/_impl/schema/cloud-schema.yaml new file mode 100644 index 00000000..78355abd --- /dev/null +++ b/src/pushsource/_impl/schema/cloud-schema.yaml @@ -0,0 +1,258 @@ +--- +# Schema for metadata file "resources.yaml" accompanying a +# cloud staged source. +# +# For general information about staging directories, see: +# https://release-engineering.github.io/pushsource/sources/staged.html +# + +$schema: http://json-schema.org/draft-07/schema# +$id: http://release-engineering.github.io/pushsource/cloud-schema.yaml + + +############################################################################### +# Subschemas +definitions: + ami_release: + # Release metadata for an AMI. + type: object + properties: + product: + type: string + minLength: 1 + version: + $ref: "#/definitions/optional_string" + base_product: + $ref: "#/definitions/optional_string" + base_version: + $ref: "#/definitions/optional_string" + variant: + $ref: "#/definitions/optional_string" + arch: + type: string + enum: + - arm64 + - x86_64 + respin: + type: integer + type: + $ref: "#/definitions/optional_string" + enum: ['ga', 'beta', null] + date: + type: string + minLength: 1 + pattern: "^[0-9]{8}$" + required: + - product + - date + - arch + - respin + + optional_string: + # A field which may hold a non-empty string, or null. + type: + - string + - "null" + minLength: 1 + + ami_billing_codes: + # Billing codes for an AMI + type: + - object + - "null" + properties: + name: + type: string + codes: + type: array + items: + type: string + required: + - name + - codes + + image: + type: object + properties: + path: + type: string + architecture: + type: string + +type: object +properties: + api: + type: string + enum: ["v1"] + resource: + type: string + enum: ["CloudImage"] + images: + type: array + items: + $ref: "#/definitions/image" + build: + type: object + properties: + name: string + version: string + respin: string + description: + type: string + boot_mode: + enum: [ 'hybrid', 'uefi', 'legacy', null ] + type: + enum: ['AMI', 'VHD', null] + release: + $ref: "#/definitions/ami_release" + + region: + # AWS region to which this AMI should be pushed. + type: string + minLength: 1 + + type: + # Billing type for the image. + type: string + enum: + - hourly + - access + - marketplace + + virtualization: + # Virtualization type. + type: string + enum: + - hvm + + volume: + type: string + enum: + - standard + - gp2 + - gp3 + - io1 + - io2 + - st1 + - sc1 + + root_device: + type: string + minLength: 1 + + description: + $ref: "#/definitions/optional_string" + + sriov_net_support: + type: + - string + - "null" + enum: + - simple + - null + + ena_support: + type: + - boolean + - "null" + + uefi_support: + type: + - boolean + - "null" + + billing_codes: + $ref: "#/definitions/ami_billing_codes" + + boot_mode: + enum: [ 'hybrid', 'uefi', 'legacy', null ] + + public_image: + type: + - boolean + - "null" + release_notes: + $ref: "#/definitions/optional_string" + + usage_instructions: + $ref: "#/definitions/optional_string" + + recommended_instance_type: + $ref: "#/definitions/optional_string" + + marketplace_entity_type: + $ref: "#/definitions/optional_string" + + scanning_port: + type: + - number + - "null" + minimum: 0 + maximum: 65536 + + user_name: + $ref: "#/definitions/optional_string" + version_title: + $ref: "#/definitions/optional_string" + marketplace_title_template: + $ref: "#/definitions/optional_string" + marketplace_name: + $ref: "#/definitions/optional_string" + security_groups: + type: + - array + - "null" + items: + type: object + properties: + ip_protocol: + type: string + ip_ranges: + type: array + items: + type: string + if: + properties: + ip_protocol: + enum: ["icmp", "icmpv6"] + then: + properties: + from_port: + type: number + minimum: -1 + maximum: 255 + to_port: + type: number + minimum: -1 + maximum: 255 + else: + properties: + from_port: + type: number + minimum: 0 + maximum: 65536 + to_port: + type: number + minimum: 0 + maximum: 65536 + + access_endpoint_url: + type: + - object + - "null" + properties: + port: + type: number + minimum: 0 + maximum: 65536 + protocol: + enum: ["http", "https"] + +required: +- api +- resource +- images +- build +- description + +additionalProperties: false diff --git a/tests/baseline/cases/staged-simple-cloud.yml b/tests/baseline/cases/staged-simple-cloud.yml new file mode 100644 index 00000000..7078f8fa --- /dev/null +++ b/tests/baseline/cases/staged-simple-cloud.yml @@ -0,0 +1,234 @@ +# A pushsource library testcase. +# +# This file was generated from a template. +# To regenerate, run test_baseline.py with PUSHSOURCE_UPDATE_BASELINE=1. + +# URL of Source to test. +url: "staged:{{ src_dir }}/tests/staged/data/simple_cloud" + +# Push items generated from above. +items: +- AmiPushItem: + access_endpoint_url: null + billing_codes: null + boot_mode: hybrid + build: null + build_info: + id: null + name: rhel + release: '1' + version: '9.4' + description: build2 sample + dest: + - starmap + ena_support: null + image_id: null + marketplace_entity_type: null + marketplace_name: null + marketplace_title_template: null + md5sum: null + name: something1.raw.xz + origin: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2 + public_image: null + recommended_instance_type: null + region: null + release: + arch: x86_64 + base_product: null + base_version: null + date: 2024-10-31 + product: rhel + respin: 1 + type: null + variant: null + version: null + release_notes: null + root_device: null + scanning_port: null + security_groups: [] + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + signing_key: null + src: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/something1.raw.xz + sriov_net_support: null + state: PENDING + type: AMI + uefi_support: null + usage_instructions: null + user_name: null + version_title: null + virtualization: null + volume: null +- AmiPushItem: + access_endpoint_url: null + billing_codes: null + boot_mode: hybrid + build: null + build_info: + id: null + name: rhel + release: '1' + version: '9.4' + description: build2 sample + dest: + - starmap + ena_support: null + image_id: null + marketplace_entity_type: null + marketplace_name: null + marketplace_title_template: null + md5sum: null + name: something2.raw.xz + origin: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2 + public_image: null + recommended_instance_type: null + region: null + release: + arch: arm64 + base_product: null + base_version: null + date: 2024-10-31 + product: rhel + respin: 1 + type: null + variant: null + version: null + release_notes: null + root_device: null + scanning_port: null + security_groups: [] + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + signing_key: null + src: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/something2.raw.xz + sriov_net_support: null + state: PENDING + type: AMI + uefi_support: null + usage_instructions: null + user_name: null + version_title: null + virtualization: null + volume: null +- AmiPushItem: + access_endpoint_url: null + billing_codes: null + boot_mode: hybrid + build: null + build_info: + id: null + name: rhel-ec2 + release: '1' + version: '9.4' + description: build3 sample + dest: + - starmap + ena_support: null + image_id: null + marketplace_entity_type: null + marketplace_name: null + marketplace_title_template: null + md5sum: null + name: something1.raw.xz + origin: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3 + public_image: null + recommended_instance_type: null + region: null + release: + arch: x86_64 + base_product: null + base_version: null + date: 2024-10-31 + product: rhel + respin: 1 + type: ga + variant: Fake-Variant + version: Fake-Version + release_notes: null + root_device: null + scanning_port: null + security_groups: [] + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + signing_key: null + src: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/something1.raw.xz + sriov_net_support: null + state: PENDING + type: AMI + uefi_support: null + usage_instructions: null + user_name: null + version_title: null + virtualization: null + volume: null +- VHDPushItem: + boot_mode: null + build: null + build_info: + id: null + name: rhel-ec2 + release: '1' + version: '9.4' + description: build1 sample + dest: + - starmap + disk_version: null + generation: V2 + legacy_sku_id: null + marketplace_name: null + marketplace_title_template: null + md5sum: null + name: something1.raw.xz + origin: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1 + recommended_sizes: [] + release: + arch: x86_64 + base_product: null + base_version: null + date: 2024-10-31 + product: rhel + respin: 1 + type: null + variant: null + version: null + sas_uri: null + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + signing_key: null + sku_id: null + src: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/something1.raw.xz + state: PENDING + support_legacy: false +- VHDPushItem: + boot_mode: null + build: null + build_info: + id: null + name: rhel-ec2 + release: '1' + version: '9.4' + description: build1 sample + dest: + - starmap + disk_version: null + generation: V2 + legacy_sku_id: null + marketplace_name: null + marketplace_title_template: null + md5sum: null + name: something2.raw.xz + origin: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1 + recommended_sizes: [] + release: + arch: arm64 + base_product: null + base_version: null + date: 2024-10-31 + product: rhel + respin: 1 + type: null + variant: null + version: null + sas_uri: null + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + signing_key: null + sku_id: null + src: {{ src_dir }}/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/something2.raw.xz + state: PENDING + support_legacy: false diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/bad_path/badpath1.raw.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/bad_path/badpath1.raw.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/bad_path/resources.yaml b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/bad_path/resources.yaml new file mode 100644 index 00000000..1559593a --- /dev/null +++ b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/bad_path/resources.yaml @@ -0,0 +1,12 @@ +api: v1 +resource: CloudImage +images: + - path: "/etc/home/badpath1.raw.xz" + architecture: x86_64 +build: + name: rhel-ec2 + version: "9.4" + respin: "1" +description: "build1 sample" +boot_mode: hybrid +type: AMI diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/resources.yaml b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/resources.yaml new file mode 100644 index 00000000..a4ae91bd --- /dev/null +++ b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/resources.yaml @@ -0,0 +1,16 @@ +api: v1 +resource: CloudImage +images: + - path: something1.raw.xz + architecture: x86_64 + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + - path: something2.raw.xz + architecture: arm64 + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 +build: + name: rhel-ec2 + version: "9.4" + respin: "1" +description: "build1 sample" +boot_mode: hybrid +type: VHD diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/sample1.vhd.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/sample1.vhd.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/sample2.vhd.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build1/sample2.vhd.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/resources.yaml b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/resources.yaml new file mode 100644 index 00000000..180f3156 --- /dev/null +++ b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/resources.yaml @@ -0,0 +1,16 @@ +api: v1 +resource: CloudImage +images: + - path: something1.raw.xz + architecture: x86_64 + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 + - path: something2.raw.xz + architecture: arm64 + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 +build: + name: rhel + version: "9.4" + respin: "1" +description: "build2 sample" +boot_mode: hybrid +type: AMI \ No newline at end of file diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/sample1.raw.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/sample1.raw.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/sample2.raw.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build2/sample2.raw.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/resources.yaml b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/resources.yaml new file mode 100644 index 00000000..407d6203 --- /dev/null +++ b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/resources.yaml @@ -0,0 +1,23 @@ +api: v1 +resource: CloudImage +images: + - path: something1.raw.xz + architecture: x86_64 + sha256sum: 04db0c39efb31518ff79bf98d1c27256d46cdc72b967a5b2094a6efec3166df2 +build: + name: rhel-ec2 + version: "9.4" + respin: "1" +release: + arch: x86_64 + base_product: null + base_version: null + date: "20200511" + product: Fake-Product + respin: 1 + type: ga + variant: Fake-Variant + version: Fake-Version +description: "build3 sample" +boot_mode: hybrid +type: AMI \ No newline at end of file diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/sample1.raw.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/build3/sample1.raw.xz new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/empty_resource/resources.yaml b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/empty_resource/resources.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/no_resources_file/sample1.raw.xz b/tests/staged/data/simple_cloud/starmap/CLOUD_IMAGES/no_resources_file/sample1.raw.xz new file mode 100644 index 00000000..e69de29b