From 6bc507319da7a01d1631f71345aa3a74705f484a Mon Sep 17 00:00:00 2001 From: Qingmin Duanmu Date: Fri, 20 Dec 2024 13:46:56 +0800 Subject: [PATCH] feat: initialize command for cac to oscal transformation --- .../cli/test_sync_cac_content_cmd.py | 39 ++++++++++++ trestlebot/cli/commands/sync_cac_content.py | 60 +++++++++++++++++++ trestlebot/cli/root.py | 2 + 3 files changed, 101 insertions(+) create mode 100644 tests/trestlebot/cli/test_sync_cac_content_cmd.py create mode 100644 trestlebot/cli/commands/sync_cac_content.py diff --git a/tests/trestlebot/cli/test_sync_cac_content_cmd.py b/tests/trestlebot/cli/test_sync_cac_content_cmd.py new file mode 100644 index 00000000..4671c583 --- /dev/null +++ b/tests/trestlebot/cli/test_sync_cac_content_cmd.py @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Red Hat, Inc. + +""" Unit test for sync-cac-content command""" +import pathlib +from typing import Tuple + +from click.testing import CliRunner +from git import Repo + +from trestlebot.cli.commands.sync_cac_content import sync_cac_content_cmd + + +test_product = "ocp4" + + +def test_missing_required_option(tmp_repo: Tuple[str, Repo]) -> None: + """Tests missing required options in sync-cac-content command.""" + + repo_dir, _ = tmp_repo + repo_path = pathlib.Path(repo_dir) + + runner = CliRunner() + result = runner.invoke( + sync_cac_content_cmd, + [ + "--product", + test_product, + "--repo-path", + str(repo_path.resolve()), + "--committer-email", + "test@email.com", + "--committer-name", + "test name", + "--branch", + "test", + ], + ) + assert result.exit_code == 2 diff --git a/trestlebot/cli/commands/sync_cac_content.py b/trestlebot/cli/commands/sync_cac_content.py new file mode 100644 index 00000000..6f2a3067 --- /dev/null +++ b/trestlebot/cli/commands/sync_cac_content.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Red Hat, Inc. + +"""Module for sync cac content command""" +import logging +from typing import Any + +import click + +from trestlebot.cli.options.common import common_options, git_options, handle_exceptions + + +logger = logging.getLogger(__name__) + + +@click.command( + name="sync-cac-content", + help="Transform CaC content to component definition in OSCAL.", +) +@click.pass_context +@common_options +@git_options +@click.option( + "--cac-content-root", + help="Root of the CaC content project.", + required=True, +) +@click.option( + "--product", + type=str, + help="Product to build OSCAL component definition with", + required=True, +) +@click.option( + "--cac-profile", + type=str, + help="CaC profile used to collect product data for transformation", + required=True, +) +@click.option( + "--oscal-profile", + type=str, + help="Main profile href, or name of the profile in trestle workspace", + required=True, +) +@click.option( + "--component-definition-type", + type=click.Choice(["service", "validation"]), + help="Type of component definition. Default: service", + required=False, + default="service", +) +@handle_exceptions +def sync_cac_content_cmd(ctx: click.Context, **kwargs: Any) -> None: + """Transform CaC content to OSCAL component definition.""" + + # Steps: + # 1. Check options, logger errors if any and exit. + # 2. Create a new task to run the data transformation. + # 3. Initialize a Trestlebot object and run the task(s). diff --git a/trestlebot/cli/root.py b/trestlebot/cli/root.py index 53837b7e..6cb0afc2 100644 --- a/trestlebot/cli/root.py +++ b/trestlebot/cli/root.py @@ -10,6 +10,7 @@ from trestlebot.cli.commands.create import create_cmd from trestlebot.cli.commands.init import init_cmd from trestlebot.cli.commands.rule_transform import rule_transform_cmd +from trestlebot.cli.commands.sync_cac_content import sync_cac_content_cmd from trestlebot.cli.commands.sync_upstreams import sync_upstreams_cmd @@ -33,4 +34,5 @@ def root_cmd(ctx: click.Context) -> None: root_cmd.add_command(autosync_cmd) root_cmd.add_command(create_cmd) root_cmd.add_command(rule_transform_cmd) +root_cmd.add_command(sync_cac_content_cmd) root_cmd.add_command(sync_upstreams_cmd)