Skip to content
Open
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
45 changes: 18 additions & 27 deletions checkov/helm/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,48 +171,39 @@ def check_system_deps(self) -> str | None:

@staticmethod
def _parse_output(target_dir: str, output: bytes) -> None:
# Helm output is a series of YAML documents separated by '---' (document start marker).
# Each template starts with a comment line that indicates the source file, but a template
# may contain multiple documents (and can itself start with a marker).
output_str = str(output, 'utf-8')
reader = io.StringIO(output_str)
cur_source_file = None
cur_writer = None
last_line_dashes = False
line_num = 1
for s in reader:
s = s.rstrip()
if s == '---':
last_line_dashes = True
continue

if last_line_dashes:
# The next line should contain a "Source" comment saying the name of the file it came from
# So we will close the old file, open a new file, and write the dashes from last iteration plus this line

if not s.startswith('# Source: '):
raise Exception(f'Line {line_num}: Expected line to start with # Source: {s}')
source = s[10:]
if source != cur_source_file:
if cur_writer:
cur_writer.close()
file_path = os.path.join(target_dir, source)
parent = os.path.dirname(file_path)
os.makedirs(parent, exist_ok=True)
cur_source_file = source
cur_writer = open(os.path.join(target_dir, source), 'a')

elif last_line_dashes:
if s.startswith('# Source: '):
source = s[10:]
if source != cur_source_file:
if cur_writer:
cur_writer.close()
file_path = os.path.join(target_dir, source)
parent = os.path.dirname(file_path)
os.makedirs(parent, exist_ok=True)
cur_source_file = source
cur_writer = open(os.path.join(target_dir, source), 'a')

if cur_writer:
cur_writer.write('---' + os.linesep)
cur_writer.write(s + os.linesep)

last_line_dashes = False
else:
if s.startswith('# Source: '):
raise Exception(f'Line {line_num}: Unexpected line starting with # Source: {s}')

if not cur_writer:
continue
else:
cur_writer.write(s + os.linesep)

line_num += 1
elif cur_writer:
cur_writer.write(s + os.linesep)

if cur_writer:
cur_writer.close()
Expand Down
4 changes: 4 additions & 0 deletions tests/helm/runner/resources/multiple/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v2
name: multiple-resources
description: A test Helm chart
version: 0.1.0
12 changes: 12 additions & 0 deletions tests/helm/runner/resources/multiple/templates/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: one
data:
key: "value"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: two
Empty file.
29 changes: 29 additions & 0 deletions tests/helm/test_runner_multiple_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from __future__ import annotations

from pathlib import Path

import pytest

from checkov.common.output.report import CheckType
from checkov.helm.runner import Runner
from tests.helm.utils import helm_exists

RESOURCES_PATH = Path(__file__).parent / "runner" / "resources"


@pytest.mark.skipif(not helm_exists(), reason="helm not installed")
def test_multiple_resources():
runner = Runner()
report = runner.run(
root_folder=str(RESOURCES_PATH / "multiple"),
)

# The helm chart contains one template with two resources.
# Neither resource has a namespace.

assert len(report.failed_checks) == 2
assert report.check_type == CheckType.HELM

assert len(report.resources) == 2
for resource in report.resources:
assert "templates/test.yaml" in resource
Loading