Skip to content

trestle.core.commands.create

trestle.core.commands.create ¤

Trestle Create CommandPlusDocs.

Attributes¤

logger = logging.getLogger(__name__) module-attribute ¤

Classes¤

CreateCmd ¤

Bases: CommandPlusDocs

Create a sample OSCAL model in trestle workspace or create new elements within a given model.

Source code in trestle/core/commands/create.py
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
class CreateCmd(CommandPlusDocs):
    """Create a sample OSCAL model in trestle workspace or create new elements within a given model."""

    name = 'create'

    def _init_arguments(self) -> None:
        self.add_argument('-t', '--type', help='Type of model if created anew.', choices=const.MODEL_TYPE_LIST)
        self.add_argument('-o', '--output', help='Name of the output created model.')
        self.add_argument(const.IOF_SHORT, const.IOF_LONG, help=const.IOF_HELP, action='store_true')
        self.add_argument(
            '-x', '--extension', help='Type of file output.', choices=['json', 'yaml', 'yml'], default='json'
        )
        self.add_argument(
            '-f', '--file', help='Optional existing OSCAL file that will have elements created within it.', type=str
        )
        self.add_argument(
            '-e', '--element', help='Optional path of element to be created whithin the specified file.', type=str
        )

    def _run(self, args: argparse.Namespace) -> int:
        """
        Execute the create command.

        Notes
            Either a new model will be created of the specified type,
            or an existing file will have new elements added within it.
        """
        try:
            # Normal create path
            if args.type and args.output:
                object_type = ElementPath(args.type).get_type()
                return self.create_object(args.type, object_type, args)
            # Add path
            elif args.file and args.element:
                add = Add()
                return add.add_from_args(args)

            raise err.TrestleIncorrectArgsError(
                'Create requires either a model type and output name, or a file and element path.'
            )

        except Exception as e:  # pragma: no cover
            return err.handle_generic_command_exception(e, logger, 'Error while creating a sample OSCAL model')

    @classmethod
    def create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:
        """Create a top level OSCAL object within the trestle directory, leveraging functionality in add."""
        log.set_log_level_from_args(args)
        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.
        if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):
            raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')

        plural_path = ModelUtils.model_type_to_model_dir(model_alias)

        desired_model_dir = trestle_root / plural_path / args.output

        desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)

        if desired_model_path.exists():
            raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')

        # Create sample model.
        sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)
        # Presuming top level level model not sure how to do the typing for this.
        sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'
        sample_model.metadata.last_modified = datetime.now().astimezone()
        sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION
        sample_model.metadata.version = '0.0.0'

        top_element = Element(sample_model, model_alias)

        create_action = CreatePathAction(desired_model_path.resolve(), True)
        write_action = WriteFileAction(
            desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)
        )

        # create a plan to write the directory and file.
        create_plan = Plan()
        create_plan.add_action(create_action)
        create_plan.add_action(write_action)
        create_plan.execute()
        return CmdReturnCodes.SUCCESS.value
Attributes¤
name = 'create' class-attribute instance-attribute ¤
Functions¤
create_object(model_alias, object_type, args) classmethod ¤

Create a top level OSCAL object within the trestle directory, leveraging functionality in add.

Source code in trestle/core/commands/create.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
@classmethod
def create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:
    """Create a top level OSCAL object within the trestle directory, leveraging functionality in add."""
    log.set_log_level_from_args(args)
    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.
    if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):
        raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')

    plural_path = ModelUtils.model_type_to_model_dir(model_alias)

    desired_model_dir = trestle_root / plural_path / args.output

    desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)

    if desired_model_path.exists():
        raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')

    # Create sample model.
    sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)
    # Presuming top level level model not sure how to do the typing for this.
    sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'
    sample_model.metadata.last_modified = datetime.now().astimezone()
    sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION
    sample_model.metadata.version = '0.0.0'

    top_element = Element(sample_model, model_alias)

    create_action = CreatePathAction(desired_model_path.resolve(), True)
    write_action = WriteFileAction(
        desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)
    )

    # create a plan to write the directory and file.
    create_plan = Plan()
    create_plan.add_action(create_action)
    create_plan.add_action(write_action)
    create_plan.execute()
    return CmdReturnCodes.SUCCESS.value

handler: python