Exemple #1
0
def test_load_file(tmp_dir):
    """Test load file."""
    json_file_path = pathlib.Path.joinpath(test_utils.JSON_TEST_DATA_PATH,
                                           'sample-target-definition.json')
    yaml_file_path = pathlib.Path.joinpath(test_utils.YAML_TEST_DATA_PATH,
                                           'good_target.yaml')

    assert fs.load_file(json_file_path) is not None
    assert fs.load_file(yaml_file_path) is not None

    try:
        sample_file_path = tmp_dir.joinpath('sample.txt')
        with open(sample_file_path, 'w'):
            fs.load_file(sample_file_path)
    except TrestleError:
        pass
Exemple #2
0
def parse_file(file_name: str, model_name: str):
    """Load a model from the file.

    Argument:
        model_name: it should be of the form <module>.<class>
                    <class> should be a Pydantic class that supports `parse_obj` method
    """
    warnings.warn('trestle.parser functions are deprecated',
                  DeprecationWarning)
    if file_name is None:
        raise TrestleError('file_name is required')

    data = fs.load_file(file_name)
    rkey = root_key(data)
    if model_name is None:
        model_name = to_full_model_name(rkey)
    return parse_dict(data[rkey], model_name)
Exemple #3
0
def parse_file(file_name: pathlib.Path,
               model_name: Optional[str]) -> OscalBaseModel:
    """
    Load an oscal file from the file system where the oscal model type is not known.

    Args:
        file_name: File path
        model_name: it should be of the form module.class which is derived from OscalBaseModel
    """
    if file_name is None:
        raise TrestleError('file_name is required')

    data = fs.load_file(file_name)
    rkey = root_key(data)
    if model_name is None:
        model_name = to_full_model_name(rkey)
    return _parse_dict(data[rkey], model_name)
    def _run(self, args: argparse.Namespace) -> int:
        """Top level import run command."""
        log.set_log_level_from_args(args)

        logger.debug('Entering import run.')

        # 1. Validate input arguments are as expected.
        # This code block may never be reached as the argument is declared to be required.

        # 1.1 Check that input file given exists.
        input_file = pathlib.Path(args.file)
        if not input_file.exists():
            logger.error(f'Input file {args.file} does not exist.')
            return 1

        # 1.2 Bad working directory if not running from current working directory
        cwd = pathlib.Path.cwd().resolve()
        trestle_root = fs.get_trestle_project_root(cwd)
        if trestle_root is None:
            logger.error(
                f'Current working directory: {cwd} is not within a trestle project.'
            )
            return 1

        # 2. Importing a file that is already inside a trestle-initialized dir is bad
        trestle_root = trestle_root.resolve()
        try:
            input_file.absolute().relative_to(trestle_root)
        except ValueError:
            # An exception here is good: it means that the input file is not inside a trestle dir.
            pass
        else:
            logger.error(
                'Input file cannot be from current trestle project. Use duplicate instead.'
            )
            return 1

        # 3. Work out typing information from input suffix.
        try:
            content_type = FileContentType.to_content_type(input_file.suffix)
        except TrestleError as err:
            logger.debug(f'FileContentType.to_content_type() failed: {err}')
            logger.error(
                f'Import failed, could not work out content type from file suffix: {err}'
            )
            return 1

        # 4. Load input and parse for model

        # 4.1 Load from file
        try:
            data = fs.load_file(input_file.absolute())
        except JSONDecodeError as err:
            logger.debug(f'fs.load_file() failed: {err}')
            logger.error(f'Import failed, JSON error loading file: {err}')
            return 1
        except TrestleError as err:
            logger.debug(f'fs.load_file() failed: {err}')
            logger.error(f'Import failed, error loading file: {err}')
            return 1
        except PermissionError as err:
            logger.debug(f'fs.load_file() failed: {err}')
            logger.error(
                f'Import failed, access permission error loading file: {err}')
            return 1

        # 4.2 root key check
        try:
            parent_alias = parser.root_key(data)
        except TrestleError as err:
            logger.debug(f'parser.root_key() failed: {err}')
            logger.error(
                f'Import failed, failed to parse input file for root key: {err}'
            )
            return 1

        # 4.3 parse the model
        parent_model_name = parser.to_full_model_name(parent_alias)
        try:
            parent_model = parser.parse_file(input_file.absolute(),
                                             parent_model_name)
        except TrestleError as err:
            logger.debug(f'parser.parse_file() failed: {err}')
            logger.error(
                f'Import failed, failed to parse valid contents of input file: {err}'
            )
            return 1

        # 5. Work out output directory and file
        plural_path: str
        plural_path = parent_alias
        # Cater to POAM
        if parent_alias[-1] != 's':
            plural_path = parent_alias + 's'

        desired_model_dir = trestle_root / plural_path
        # args.output is presumed to be assured as it is declared to be required
        if args.output:
            desired_model_path = desired_model_dir / args.output / (
                parent_alias + input_file.suffix)

        if desired_model_path.exists():
            logger.error(
                f'OSCAL file to be created here: {desired_model_path} exists.')
            logger.error('Aborting trestle import.')
            return 1

        # 6. Prepare actions and plan
        top_element = Element(parent_model.oscal_read(input_file))
        create_action = CreatePathAction(desired_model_path.absolute(), True)
        write_action = WriteFileAction(desired_model_path.absolute(),
                                       top_element, content_type)

        # create a plan to create the directory and imported file.
        import_plan = Plan()
        import_plan.add_action(create_action)
        import_plan.add_action(write_action)

        try:
            import_plan.simulate()
        except TrestleError as err:
            logger.debug(f'import_plan.simulate() failed: {err}')
            logger.error(
                f'Import failed, error in testing import operation: {err}')
            return 1

        try:
            import_plan.execute()
        except TrestleError as err:
            logger.debug(f'import_plan.execute() failed: {err}')
            logger.error(
                f'Import failed, error in actual import operation: {err}')
            return 1

        # 7. Leave the rest to trestle split
        return 0