Skip to content

Commit

Permalink
Merge pull request #358 from iriusrisk/hotfix/OPT-1105
Browse files Browse the repository at this point in the history
[hotfix/OPT-1105] to main
  • Loading branch information
dfernandezvigo authored Feb 19, 2024
2 parents 3bbd28b + 4a746b5 commit 3174aec
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 28 deletions.
12 changes: 10 additions & 2 deletions sl_util/sl_util/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from magic import Magic
from starlette.datastructures import UploadFile

SUPPORTED_ENCODINGS = ['utf-8', 'utf-16', 'utf-8-ignore']


def copy_to_disk(diag_file: tempfile.SpooledTemporaryFile, suffix: str):
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as ntf:
Expand Down Expand Up @@ -37,8 +39,14 @@ def get_byte_data_from_upload_file(upload_file: UploadFile) -> bytes:
return upload_file.file.read()


def read_byte_data(data: bytes, encoding: str = 'utf-8') -> str:
return data.decode(encoding)
def read_byte_data(data: bytes) -> str:
for encoding in SUPPORTED_ENCODINGS:
try:
return data.decode(encoding=encoding)
except UnicodeError:
pass

raise UnicodeError(f'File content cannot be decoded, supported encodings: {SUPPORTED_ENCODINGS}')


def get_file_type_by_content(file_content: bytes) -> str:
Expand Down
14 changes: 10 additions & 4 deletions sl_util/sl_util/json_utils.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import json
import logging
from typing import Union

import yaml

from otm.otm.entity.otm import OTM
from sl_util.sl_util.file_utils import read_byte_data

logger = logging.getLogger(__name__)


def __yaml_data_as_str(data: Union[str, bytes]) -> str:
return data if isinstance(data, str) else read_byte_data(data)


def get_otm_as_json(otm: OTM):
logger.info("getting OTM contents as JSON")
return json.dumps(otm.json(), indent=2)


def yaml_data_as_str(data) -> str:
return data if isinstance(data, str) else data.decode()
def read_yaml(data: bytes, loader=yaml.SafeLoader) -> dict:
return yaml.load(__yaml_data_as_str(data), Loader=loader)


def yaml_reader(data, loader=yaml.BaseLoader):
return yaml.load(yaml_data_as_str(data), Loader=loader)
def read_json(data: bytes) -> dict:
return json.loads(__yaml_data_as_str(data))
7 changes: 3 additions & 4 deletions slp_cft/slp_cft/load/cft_loader.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging

from deepmerge import always_merger

from yaml import BaseLoader, ScalarNode

from sl_util.sl_util.json_utils import yaml_reader
from sl_util.sl_util.json_utils import read_yaml
from slp_base.slp_base.errors import LoadingIacFileError
from slp_base.slp_base.provider_loader import ProviderLoader

Expand Down Expand Up @@ -33,7 +32,7 @@ class CloudformationLoader(ProviderLoader):

def __init__(self, sources):
self.sources = sources
self.yaml_reader = yaml_reader
self.yaml_reader = read_yaml
self.cloudformation = None

def load(self):
Expand All @@ -57,7 +56,7 @@ def __merge_cft_data(self, cft_data):

def __load_cft_data(self, source) -> dict:
try:
logger.debug(f"Loading iac data and reading as string")
logger.debug("Loading iac data and reading as string")

cft_data = self.yaml_reader(source, loader=get_loader())

Expand Down
2 changes: 0 additions & 2 deletions slp_drawio/tests/validate/test_drawio_validator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from unittest.mock import patch, MagicMock

import pytest
from starlette.datastructures import UploadFile, Headers

from sl_util.sl_util import secure_regex as re
from sl_util.sl_util.file_utils import get_byte_data
from sl_util.tests.util.file_utils import get_upload_file
from slp_base import DiagramFileNotValidError, CommonError
from slp_drawio.slp_drawio.validate.drawio_validator import DrawioValidator
from slp_drawio.tests.resources.test_resource_paths import wrong_mxgraphmodel_drawio, wrong_mxfile_drawio, \
Expand Down
4 changes: 2 additions & 2 deletions slp_tfplan/slp_tfplan/load/tfplan_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from networkx import nx_agraph, DiGraph

from sl_util.sl_util.file_utils import read_byte_data
from sl_util.sl_util.json_utils import yaml_reader
from sl_util.sl_util.json_utils import read_json
from slp_base import ProviderLoader, LoadingIacFileError
from slp_tfplan.slp_tfplan.load.tfplan_to_resource_dict import TfplanToResourceDict


def load_tfplan(source: bytes) -> Dict:
try:
return yaml_reader(source)
return read_json(source)
except Exception:
pass

Expand Down
2 changes: 1 addition & 1 deletion slp_tfplan/slp_tfplan/load/tfplan_to_resource_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def is_not_cloned_resource(resource: Dict) -> bool:
return 'index' not in resource or resource['index'] == '0' or resource['index'] == 'zero'
return 'index' not in resource or resource['index'] == '0' or resource['index'] == 0 or resource['index'] == 'zero'


def get_resource_id(resource: Dict) -> str:
Expand Down
4 changes: 2 additions & 2 deletions slp_tfplan/slp_tfplan/validate/tfplan_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
logger = logging.getLogger(__name__)

MIN_FILE_SIZE = 20
MAX_TFPLAN_FILE_SIZE = 5 * 1024 * 1024 # 5MB
MAX_TFGRAPH_FILE_SIZE = 2 * 1024 * 1024 # 2MB
MAX_TFPLAN_FILE_SIZE = 50 * 1024 * 1024 # 50MB
MAX_TFGRAPH_FILE_SIZE = 50 * 1024 * 1024 # 50MB

TFPLAN_MIME_TYPE = 'application/json'
TFGRAPH_MIME_TYPE = 'text/plain'
Expand Down
18 changes: 9 additions & 9 deletions slp_tfplan/tests/unit/load/test_tfplan_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def mock_load_graph(mocker, mocked_graph):
class TestTFPlanLoader:

@patch('slp_tfplan.slp_tfplan.load.tfplan_loader.load_tfgraph')
@patch('yaml.load')
@patch('json.loads')
def test_load_tfplan_and_graph(self, yaml_mock, from_agraph_mock):
# GIVEN a valid plain Terraform Plan file with no modules
yaml_mock.side_effect = [build_tfplan(resources=generate_resources(2))]
Expand All @@ -55,7 +55,7 @@ def test_load_tfplan_and_graph(self, yaml_mock, from_agraph_mock):
# AND the TFGRAPH is also loaded
assert tfplan_loader.get_tfgraph().graph['label'] == graph_label

@patch('yaml.load')
@patch('json.loads')
def test_load_no_modules(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with no modules
yaml_mock.side_effect = [build_tfplan(resources=generate_resources(2))]
Expand All @@ -79,7 +79,7 @@ def test_load_no_modules(self, yaml_mock):

assert_resource_values(resource['resource_values'])

@patch('yaml.load')
@patch('json.loads')
def test_load_only_modules(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with only modules
yaml_mock.side_effect = [build_tfplan(
Expand Down Expand Up @@ -110,7 +110,7 @@ def test_load_only_modules(self, yaml_mock):

resource_index += 1

@patch('yaml.load')
@patch('json.loads')
def test_load_nested_modules(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with nested modules
yaml_mock.side_effect = [build_tfplan(
Expand All @@ -136,7 +136,7 @@ def test_load_nested_modules(self, yaml_mock):

assert_resource_values(resource['resource_values'])

@patch('yaml.load')
@patch('json.loads')
def test_load_complex_structure(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with modules and root-level resources
yaml_mock.side_effect = [build_tfplan(
Expand Down Expand Up @@ -169,7 +169,7 @@ def test_load_complex_structure(self, yaml_mock):

assert_resource_values(resource['resource_values'])

@patch('yaml.load')
@patch('json.loads')
def test_load_resources_same_name(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with only one module
tfplan = build_tfplan(
Expand All @@ -196,7 +196,7 @@ def test_load_resources_same_name(self, yaml_mock):
assert resources[0]['resource_id'] == 'r1-addr'
assert resources[0]['resource_name'] == 'cm1-addr.r1-name'

@patch('yaml.load')
@patch('json.loads')
def test_load_modules_same_name(self, yaml_mock):
# GIVEN a valid plain Terraform Plan file with only one module
tfplan = build_tfplan(
Expand Down Expand Up @@ -233,7 +233,7 @@ def test_load_modules_same_name(self, yaml_mock):
assert resources[0]['resource_id'] == 'cm1-addr.r1-addr'
assert resources[0]['resource_name'] == 'cm1-addr.r1-name'

@patch('yaml.load')
@patch('json.loads')
def test_load_no_resources(self, yaml_mock):
# GIVEN a valid Terraform Plan file with no resources
yaml_mock.side_effect = [{'planned_values': {'root_module': {}}}]
Expand All @@ -245,7 +245,7 @@ def test_load_no_resources(self, yaml_mock):
# THEN TfplanLoader.terraform is an empty dictionary
assert tfplan_loader.terraform == {}

@patch('yaml.load')
@patch('json.loads')
def test_load_empty_tfplan(self, yaml_mock):
# GIVEN an empty TFPLAN
yaml_mock.side_effect = [{}]
Expand Down
4 changes: 2 additions & 2 deletions slp_tfplan/tests/util/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

TFPLAN_MINIMUM_STRUCTURE = {'planned_values': {'root_module': {}}}
MIN_FILE_SIZE = 20
MAX_TFPLAN_FILE_SIZE = 5 * 1024 * 1024 # 5MB
MAX_TFGRAPH_FILE_SIZE = 2 * 1024 * 1024 # 2MB
MAX_TFPLAN_FILE_SIZE = 50 * 1024 * 1024 # 50MB
MAX_TFGRAPH_FILE_SIZE = 50 * 1024 * 1024 # 50MB


#######
Expand Down

0 comments on commit 3174aec

Please sign in to comment.