Skip to content

Commit

Permalink
Add JSON output to advisory list
Browse files Browse the repository at this point in the history
Similar to the repolist --json output, do it for listing advisories that
apply to the system ("dnf advisory list") as well as for the references
currently supported Bugzilla and CVE types of references.

These follow what is output on the terminal. The exception is that the
queries with a reference (--with-bz and --with-cve) also print the
advisory name. This is just to make it a bit easier for other tools
which may already know about that advisory ID.

Example of advisory list --json:
[
  {
    "name":"FEDORA-2024-143f0443e1",
    "type":"unspecified",
    "severity":"None",
    "nevra":"yum-4.19.2-1.fc40.noarch",
    "buildtime":"2024-04-19 21:20:20"
  },
  {
    "name":"FEDORA-2024-1e8a70c30e",
    "type":"enhancement",
    "severity":"None",
    "nevra":"zstd-1.5.6-1.fc40.aarch64",
    "buildtime":"2024-04-19 21:20:20"
  }
]

Example of advisory list --with-bz --json:
[
  {
    "advisory_name":"FEDORA-2024-0c9d3b51d4",
    "advisory_type":"security",
    "advisory_severity":"security",
    "advisory_buildtime":"2024-05-02 01:55:56",
    "nevra":"tpm2-tss-fapi-4.1.0-1.fc40.aarch64",
    "references":[
      {
        "reference_id":"2271763",
        "reference_type":"bugzilla",
      },
      {
        "reference_id":"2277437",
        "reference_type":"bugzilla",
      }
    ]
  }
]
  • Loading branch information
stewartsmith authored and kontura committed Jun 14, 2024
1 parent 28acb8d commit 12c73b2
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 10 deletions.
19 changes: 16 additions & 3 deletions dnf5/commands/advisory/advisory_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,19 @@ void AdvisoryListCommand::process_and_print_queries(

std::vector<std::unique_ptr<libdnf5::cli::output::IAdvisoryPackage>> cli_installed_pkgs;
std::vector<std::unique_ptr<libdnf5::cli::output::IAdvisoryPackage>> cli_not_installed_pkgs;
std::string reference_type;
if (with_bz->get_value()) {
libdnf5::cli::output::print_advisorylist_references_table(not_installed_pkgs, installed_pkgs, "bugzilla");
reference_type = "bugzilla";
} else if (with_cve->get_value()) {
libdnf5::cli::output::print_advisorylist_references_table(not_installed_pkgs, installed_pkgs, "cve");
reference_type = "cve";
}
if (with_bz->get_value() || with_cve->get_value()) {
if (ctx.get_json_output_requested())
libdnf5::cli::output::print_advisorylist_references_json(
not_installed_pkgs, installed_pkgs, reference_type);
else
libdnf5::cli::output::print_advisorylist_references_table(
not_installed_pkgs, installed_pkgs, reference_type);
} else {
cli_installed_pkgs.reserve(installed_pkgs.size());
for (const auto & obj : installed_pkgs) {
Expand All @@ -79,7 +88,11 @@ void AdvisoryListCommand::process_and_print_queries(
for (const auto & obj : not_installed_pkgs) {
cli_not_installed_pkgs.emplace_back(new output::AdvisoryPackageAdapter(obj));
}
libdnf5::cli::output::print_advisorylist_table(cli_not_installed_pkgs, cli_installed_pkgs);
if (ctx.get_json_output_requested()) {
libdnf5::cli::output::print_advisorylist_json(cli_not_installed_pkgs, cli_installed_pkgs);
} else {
libdnf5::cli::output::print_advisorylist_table(cli_not_installed_pkgs, cli_installed_pkgs);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions dnf5/commands/advisory/advisory_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include "advisory_subcommand.hpp"

#include <dnf5/shared_options.hpp>

namespace dnf5 {

class AdvisoryListCommand : public AdvisorySubCommand {
Expand All @@ -31,6 +33,7 @@ class AdvisoryListCommand : public AdvisorySubCommand {
void set_argument_parser() override {
AdvisorySubCommand::set_argument_parser();
get_argument_parser_command()->set_description(_("List advisories"));
create_json_option(*this);
}

protected:
Expand Down
9 changes: 9 additions & 0 deletions include/libdnf5-cli/output/advisorylist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,20 @@ LIBDNF_CLI_API void print_advisorylist_table(
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_not_installed,
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_installed);

LIBDNF_CLI_API void print_advisorylist_json(
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_not_installed,
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_installed);

LIBDNF_CLI_API void print_advisorylist_references_table(
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_not_installed,
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_installed,
std::string reference_type);

LIBDNF_CLI_API void print_advisorylist_references_json(
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_not_installed,
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_installed,
std::string reference_type);

} // namespace libdnf5::cli::output

#endif // LIBDNF5_CLI_OUTPUT_ADVISORYLIST_HPP
91 changes: 84 additions & 7 deletions libdnf5-cli/output/advisorylist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include "utils/string.hpp"

#include <json.h>
#include <libsmartcols/libsmartcols.h>
#include <unistd.h>

#include <iostream>

namespace libdnf5::cli::output {

namespace {
Expand Down Expand Up @@ -72,6 +75,14 @@ void add_line_into_advisorylist_table(

} // namespace

static std::string get_reference_type_pretty_name(std::string type) {
if (type == "bugzilla") {
return "Bugzilla";
} else if (type == "cve") {
return "CVE";
}
return type;
}

void print_advisorylist_table(
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_not_installed,
Expand Down Expand Up @@ -104,18 +115,65 @@ void print_advisorylist_table(
scols_unref_table(table);
}

static json_object * adv_pkg_as_json(auto & adv_pkg) {
auto advisory = adv_pkg->get_advisory();
json_object * json_advisory = json_object_new_object();
json_object_object_add(json_advisory, "name", json_object_new_string(advisory->get_name().c_str()));
json_object_object_add(json_advisory, "type", json_object_new_string(advisory->get_type().c_str()));
json_object_object_add(json_advisory, "severity", json_object_new_string(advisory->get_severity().c_str()));
json_object_object_add(json_advisory, "nevra", json_object_new_string(adv_pkg->get_nevra().c_str()));
unsigned long long buildtime = advisory->get_buildtime();
json_object_object_add(
json_advisory, "buildtime", json_object_new_string(libdnf5::utils::string::format_epoch(buildtime).c_str()));
return json_advisory;
}

static json_object * adv_refs_as_json(auto & reference_type, auto & adv_pkg, auto & advisory) {
json_object * json_advisory = json_object_new_object();
json_object_object_add(json_advisory, "advisory_name", json_object_new_string(advisory.get_name().c_str()));
json_object_object_add(json_advisory, "advisory_type", json_object_new_string(advisory.get_type().c_str()));
json_object_object_add(json_advisory, "advisory_severity", json_object_new_string(advisory.get_type().c_str()));
unsigned long long buildtime = advisory.get_buildtime();
json_object_object_add(
json_advisory,
"advisory_buildtime",
json_object_new_string(libdnf5::utils::string::format_epoch(buildtime).c_str()));
json_object_object_add(json_advisory, "nevra", json_object_new_string(adv_pkg.get_nevra().c_str()));

json_object * json_adv_references = json_object_new_array();
auto references = advisory.get_references({reference_type});
for (auto reference : references) {
json_object * json_reference = json_object_new_object();
json_object_object_add(json_reference, "reference_id", json_object_new_string(reference.get_id().c_str()));
json_object_object_add(json_reference, "reference_type", json_object_new_string(reference_type.c_str()));
json_object_array_add(json_adv_references, json_reference);
}
json_object_object_add(json_advisory, "references", json_adv_references);
return json_advisory;
}


void print_advisorylist_json(
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_not_installed,
std::vector<std::unique_ptr<IAdvisoryPackage>> & advisory_package_list_installed) {
json_object * json_advisorylist = json_object_new_array();

for (auto & adv_pkg : advisory_package_list_not_installed) {
json_object_array_add(json_advisorylist, adv_pkg_as_json(adv_pkg));
}
for (auto & adv_pkg : advisory_package_list_installed) {
json_object_array_add(json_advisorylist, adv_pkg_as_json(adv_pkg));
}
std::cout << json_object_to_json_string_ext(json_advisorylist, JSON_C_TO_STRING_PRETTY) << std::endl;
json_object_put(json_advisorylist);
}


void print_advisorylist_references_table(
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_not_installed,
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_installed,
std::string reference_type) {
std::string first_column_name;
if (reference_type == "cve") {
first_column_name = "CVE";
} else {
first_column_name = "Bugzilla";
}
struct libscols_table * table = create_advisorylist_table(first_column_name);
struct libscols_table * table = create_advisorylist_table(get_reference_type_pretty_name(reference_type));
for (auto adv_pkg : advisory_package_list_not_installed) {
auto advisory = adv_pkg.get_advisory();
auto references = advisory.get_references({reference_type});
Expand Down Expand Up @@ -149,4 +207,23 @@ void print_advisorylist_references_table(
scols_unref_table(table);
}

void print_advisorylist_references_json(
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_not_installed,
std::vector<libdnf5::advisory::AdvisoryPackage> & advisory_package_list_installed,
std::string reference_type) {
json_object * json_advisory_refs = json_object_new_array();
for (auto adv_pkg : advisory_package_list_not_installed) {
auto advisory = adv_pkg.get_advisory();
auto json_refs = adv_refs_as_json(reference_type, adv_pkg, advisory);
json_object_array_add(json_advisory_refs, json_refs);
}
for (auto adv_pkg : advisory_package_list_installed) {
auto advisory = adv_pkg.get_advisory();
auto json_refs = adv_refs_as_json(reference_type, adv_pkg, advisory);
json_object_array_add(json_advisory_refs, json_refs);
}
std::cout << json_object_to_json_string_ext(json_advisory_refs, JSON_C_TO_STRING_PRETTY) << std::endl;
json_object_put(json_advisory_refs);
}

} // namespace libdnf5::cli::output

0 comments on commit 12c73b2

Please sign in to comment.