Skip to content

Commit

Permalink
formats: Add layer level JSON consumer
Browse files Browse the repository at this point in the history
This is work towards #946

Using the Consumer abstract base class, we create a Consumer
class for the JSON format plugin that will create a list of
ImageLayer objects from the report. This is assuming the
report was created at the layer level, as is the case when
using the --live option.

As part the --live option, one can provide one or more reports
created from previous runs and the plugin will return a corresponding
internal object representation of those reports.

The implementation just uses the already existing "fill" methods
of the FileData and Package class to fill in data from the dictionary.

The layer objects are ordered based on the order of the reports in the
reports list.

Signed-off-by: Nisha K <[email protected]>
  • Loading branch information
Nisha K committed May 25, 2021
1 parent 837f3aa commit 0c46292
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions tern/formats/json/consumer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021 VMware, Inc. All Rights Reserved.
# SPDX-License-Identifier: BSD-2-Clause

"""
JSON document generator
"""

import json
import logging
import os

from tern.classes.image_layer import ImageLayer
from tern.classes.package import Package
from tern.classes.file_data import FileData
from tern.formats import consumer
from tern.utils import constants

# global logger
logger = logging.getLogger(constants.logger_name)


class ConsumerError(Exception):
"""Exception raised if a critical error has occured"""


def create_image_layer(report):
"""Given a report file, create an ImageLayer object with the metadata"""
# expect a json input, raise an error if it is not
content = {}
try:
f = open(os.path.abspath(report))
content = json.load(f)
except OSError as err:
logger.critical("Cannot access file %s: %s", report, err)
raise ConsumerError(f"Error with given report file: {report}")
except json.JSONDecodeError as err:
logger.critical("Cannot parse JSON in file %s: %s", report, err)
raise ConsumerError(f"Error with given report file: {report}")
# we should have some content but it may be empty
if not content:
raise ConsumerError("No content consumed from given report file")
# instantiate a layer and fill it
layer = ImageLayer("")
try:
layer.os_guess = content['os_guess']
for pkg in content['packages']:
pkg_obj = Package(pkg['name'])
pkg_obj.fill(pkg)
layer.add_package(pkg_obj)
for filedict in content['files']:
file_obj = FileData(filedict['name'], filedict['path'])
file_obj.fill(filedict)
layer.add_file(file_obj)
return layer
except ValueError as err:
logger.critical("Cannot find required data in report: %s", err)
return None


class JSON(consumer.Consume):
def consume_layer(self, reports):
"""Given a list json report files, created by the json generator,
create a corresponding list of image layer objects. We assume the
layers are ordered in the order or report files"""
layer_list = []
layer_count = 1
for report in reports:
layer = create_image_layer(report)
layer.layer_index = layer_count
layer_list.append(layer)
layer += 1
return layer_list

0 comments on commit 0c46292

Please sign in to comment.