Skip to content
This repository has been archived by the owner on Feb 15, 2024. It is now read-only.

Flaw References and Comments support #203

Merged
merged 4 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added
- CRUD operations for OSIDB entities Flaw Comment (create, retreive, list),
JakubFrejlach marked this conversation as resolved.
Show resolved Hide resolved
Flaw Reference (create, retrieve, list, update, delete)
## [0.2.7] - 2023-06-14
### Changed
- ensure we choose latest version of component using products-contains-component
Expand Down
333 changes: 332 additions & 1 deletion griffon/commands/entities/osidb.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,27 @@
osidb_api_v1_affects_list,
osidb_api_v1_affects_retrieve,
osidb_api_v1_affects_update,
osidb_api_v1_flaws_comments_create,
osidb_api_v1_flaws_comments_list,
osidb_api_v1_flaws_comments_retrieve,
osidb_api_v1_flaws_create,
osidb_api_v1_flaws_list,
osidb_api_v1_flaws_references_create,
osidb_api_v1_flaws_references_list,
osidb_api_v1_flaws_references_retrieve,
osidb_api_v1_flaws_references_update,
osidb_api_v1_flaws_retrieve,
osidb_api_v1_flaws_update,
osidb_api_v1_trackers_list,
osidb_api_v1_trackers_retrieve,
)
from osidb_bindings.bindings.python_client.models import Affect, Flaw, Tracker
from osidb_bindings.bindings.python_client.models import (
Affect,
Flaw,
FlawComment,
FlawReference,
Tracker,
)
from requests import HTTPError

from griffon import OSIDB_API_URL, OSIDBService, progress_bar
Expand Down Expand Up @@ -201,6 +214,324 @@ def create_flaw(ctx, **params):
return cprint(data, ctx=ctx)


# flaw comments
@flaws.group(help=f"{OSIDB_API_URL}/osidb/api/v1/flaws/<id>/comments", name="comments")
@click.pass_context
def flaw_comments(ctx):
"""OSIDB Flaw Comments."""
pass


@flaw_comments.command(name="get")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@click.option("--uuid", "comment_uuid", help="Comment UUID.", required=True)
@query_params_options(
entity="Flaw Comment",
endpoint_module=osidb_api_v1_flaws_comments_retrieve,
options_overrides={
"include_fields": {"type": click.Choice(OSIDBService.get_fields(FlawComment))},
"exclude_fields": {"type": click.Choice(OSIDBService.get_fields(FlawComment))},
"include_meta_attr": {"type": click.Choice(OSIDBService.get_meta_attr_fields(FlawComment))},
},
)
@click.pass_context
@progress_bar
def get_flaw_comment(ctx, flaw_id, comment_uuid, **params):
params = multivalue_params_to_csv(params)

session = OSIDBService.create_session()
data = session.flaws.comments.retrieve(flaw_id, comment_uuid, **params)
return cprint(data, ctx=ctx)


@flaw_comments.command(name="list")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@query_params_options(
entity="Flaw Comments",
endpoint_module=osidb_api_v1_flaws_comments_list,
options_overrides={
"include_fields": {"type": click.Choice(OSIDBService.get_fields(FlawComment))},
"exclude_fields": {"type": click.Choice(OSIDBService.get_fields(FlawComment))},
"include_meta_attr": {"type": click.Choice(OSIDBService.get_meta_attr_fields(FlawComment))},
},
)
@click.pass_context
@progress_bar
def list_flaw_comments(ctx, flaw_id, **params):
# TODO: handle pagination
# TODO: handle output
JakubFrejlach marked this conversation as resolved.
Show resolved Hide resolved
session = OSIDBService.create_session()

params = multivalue_params_to_csv(params)
data = session.flaws.comments.retrieve_list(flaw_id, **params).results
return cprint(data, ctx=ctx)


@flaw_comments.command(name="create")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@request_body_options(
endpoint_module=osidb_api_v1_flaws_comments_create,
exclude=["uuid", "created_dt"],
)
@click.pass_context
def create_flaw_comment(ctx, flaw_id, **params):
request_body_type = getattr(osidb_api_v1_flaws_comments_create, "REQUEST_BODY_TYPE", None)
if request_body_type is None:
raise click.ClickException(
"No request body template for Flaw Comment create. "
"Is correct version of osidb-bindings installed?"
)

fields = filter_request_fields(
request_body_type.get_fields(),
exclude=["uuid", "created_dt"],
)
params = multivalue_params_to_csv(params)

session = OSIDBService.create_session()

data = {field: "" for field in fields}
data.update((field, value) for field, value in params.items() if value is not None)

if ctx.obj["EDITOR"]:
data = click.edit(
text=json.dumps(data, indent=4, default=str), editor=get_editor(), require_save=False
)
data = json.loads(data)

try:
data = session.flaws.comments.create(data, flaw_id=flaw_id)
except HTTPError as e:
if ctx.obj["VERBOSE"]:
console.log(e, e.response.json())
raise click.ClickException(
"Failed to create Flaw Comment. "
"You might have insufficient permission or you've supplied malformed data. "
"Consider running griffon with -v option for verbose error log."
)
return cprint(data, ctx=ctx)


# flaw references
@flaws.group(help=f"{OSIDB_API_URL}/osidb/api/v1/flaws/<id>/references", name="references")
@click.pass_context
def flaw_references(ctx):
"""OSIDB Flaw References."""
pass


@flaw_references.command(name="get")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@click.option("--uuid", "reference_uuid", help="Reference UUID.", required=True)
@query_params_options(
entity="Flaw Reference",
endpoint_module=osidb_api_v1_flaws_references_retrieve,
options_overrides={
"include_fields": {"type": click.Choice(OSIDBService.get_fields(FlawReference))},
"exclude_fields": {"type": click.Choice(OSIDBService.get_fields(FlawReference))},
"include_meta_attr": {
"type": click.Choice(OSIDBService.get_meta_attr_fields(FlawReference))
},
},
)
@click.pass_context
@progress_bar
def get_flaw_reference(ctx, flaw_id, reference_uuid, **params):
params = multivalue_params_to_csv(params)

session = OSIDBService.create_session()
data = session.flaws.references.retrieve(flaw_id, reference_uuid, **params)
return cprint(data, ctx=ctx)


@flaw_references.command(name="list")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@query_params_options(
entity="Flaw References",
endpoint_module=osidb_api_v1_flaws_references_list,
options_overrides={
"include_fields": {"type": click.Choice(OSIDBService.get_fields(FlawReference))},
"exclude_fields": {"type": click.Choice(OSIDBService.get_fields(FlawReference))},
"include_meta_attr": {
"type": click.Choice(OSIDBService.get_meta_attr_fields(FlawReference))
},
},
)
@click.pass_context
@progress_bar
def list_flaw_references(ctx, flaw_id, **params):
# TODO: handle pagination
# TODO: handle output
session = OSIDBService.create_session()

params = multivalue_params_to_csv(params)
data = session.flaws.references.retrieve_list(flaw_id, **params).results
return cprint(data, ctx=ctx)


@flaw_references.command(name="create")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@request_body_options(
endpoint_module=osidb_api_v1_flaws_references_create,
exclude=["uuid", "created_dt"],
)
@click.pass_context
def create_flaw_reference(ctx, flaw_id, **params):
request_body_type = getattr(osidb_api_v1_flaws_references_create, "REQUEST_BODY_TYPE", None)
if request_body_type is None:
raise click.ClickException(
"No request body template for Flaw Reference create. "
"Is correct version of osidb-bindings installed?"
)

fields = filter_request_fields(
request_body_type.get_fields(),
exclude=["uuid", "created_dt"],
)
params = multivalue_params_to_csv(params)

session = OSIDBService.create_session()

data = {field: "" for field in fields}
data.update((field, value) for field, value in params.items() if value is not None)

if ctx.obj["EDITOR"]:
JakubFrejlach marked this conversation as resolved.
Show resolved Hide resolved
data = click.edit(
text=json.dumps(data, indent=4, default=str), editor=get_editor(), require_save=False
)
data = json.loads(data)

try:
data = session.flaws.references.create(data, flaw_id=flaw_id)
except HTTPError as e:
if ctx.obj["VERBOSE"]:
console.log(e, e.response.json())
raise click.ClickException(
"Failed to create Flaw Reference. "
"You might have insufficient permission or you've supplied malformed data. "
"Consider running griffon with -v option for verbose error log."
)
return cprint(data, ctx=ctx)


@flaw_references.command(name="update")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@click.option("--uuid", "reference_uuid", help="Reference UUID.", required=True)
@request_body_options(endpoint_module=osidb_api_v1_flaws_references_update, exclude=["uuid"])
@click.pass_context
def update_flaw_references(ctx, flaw_id, reference_uuid, **params):
request_body_type = getattr(osidb_api_v1_flaws_references_update, "REQUEST_BODY_TYPE", None)
if request_body_type is None:
raise click.ClickException(
"No request body template for Flaw Reference update. "
"Is correct version of osidb-bindings installed?"
)

fields = filter_request_fields(request_body_type.get_fields(), exclude=["uuid"])
params = multivalue_params_to_csv(params)

session = OSIDBService.create_session()

try:
data = session.flaws.references.retrieve(
flaw_id, reference_uuid, include_fields=",".join(fields)
)
except Exception as e:
if ctx.obj["VERBOSE"]:
console.log(e, e.response.json())
raise click.ClickException(
f"Failed to fetch Flaw Reference with ID '{reference_uuid}'. "
"Flaw or Flaw Reference either does not exist or you have insufficient permissions. "
"Consider running griffon with -v option for verbose error log."
)

data = data.to_dict()
# remove status data from OSIDB server
[data.pop(key) for key in ["dt", "env", "revision", "version"]]
data.update((field, value) for field, value in params.items() if value is not None)

if ctx.obj["EDITOR"]:
data = click.edit(text=json.dumps(data, indent=4), editor=get_editor(), require_save=False)
data = json.loads(data)

try:
data = session.flaws.references.update(flaw_id, data, reference_uuid)
except HTTPError as e:
if ctx.obj["VERBOSE"]:
console.log(e, e.response.json())
raise click.ClickException(
f"Failed to update Flaw Reference with ID '{reference_uuid}'. "
"You might have insufficient permission or you've supplied malformed data. "
"Consider running griffon with -v option for verbose error log."
)
return cprint(data, ctx=ctx)


@flaw_references.command(name="delete")
@click.option(
"--flaw-id",
"flaw_id",
help="Flaw CVE-ID or UUID.",
required=True,
)
@click.option("--uuid", "reference_uuid", help="Reference UUID.", required=True)
@click.option(
"--yes",
is_flag=True,
callback=abort_if_false,
expose_value=False,
prompt="Are you sure you want to delete Flaw Reference?",
)
@click.pass_context
def delete_flaw_references(ctx, flaw_id, reference_uuid, **params):
session = OSIDBService.create_session()
try:
data = session.flaws.references.delete(flaw_id, reference_uuid)
except HTTPError as e:
if ctx.obj["VERBOSE"]:
console.log(e, e.response.json())
raise click.ClickException(
f"Failed to delete Flaw Reference {reference_uuid}. "
"It either does not exist or you have insufficient permissions."
)
return cprint(data, ctx=ctx)


# affects
@osidb_grp.group(help=f"{OSIDB_API_URL}/osidb/api/v1/affects")
@click.pass_context
Expand Down
3 changes: 1 addition & 2 deletions griffon/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ def text_output_products_contain_component(
no_wrap=no_wrap,
)
else:

if ctx.obj["VERBOSE"] == 0: # product_version X component_name
for pv in result_tree.keys():
component_names = set()
Expand Down Expand Up @@ -920,7 +919,7 @@ def text_output_list(ctx, output, format, exclude_components, no_wrap=False):
)

# handle trackers
if "external_system_id" in output["results"][0]:
if all(key in output["results"][0] for key in ("external_system_id", "status")):
for row in output["results"]:
console.print(
row["external_system_id"],
Expand Down
Loading