Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: modify run_community_analyzer to work for custom analyzers #29

Merged
merged 1 commit into from
Feb 16, 2024
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
11 changes: 7 additions & 4 deletions run_community_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,20 @@ def main(argv: list[str] | None = None) -> None:
toolbox_path = os.getenv("TOOLBOX_PATH", "/toolbox")
output_path = os.path.join(toolbox_path, "analysis_results.json")
artifacts_path = os.getenv("ARTIFACTS_PATH", "/artifacts")
issue_map_path = None

parser = argparse.ArgumentParser("sarif_parser")
parser.add_argument(
"--analyzer",
help="Which community analyzer to run. Example: 'kube-linter'",
required=True,
required=False,
)
args = parser.parse_args(argv, namespace=CommunityAnalyzerArgs)
if argv:
args = parser.parse_args(argv, namespace=CommunityAnalyzerArgs)
# analyzer name is mandatory in case of community analyzers but not custom analyzers
if analyzer_name := args.analyzer:
issue_map_path = get_issue_map(analyzer_name)

analyzer_name = args.analyzer
issue_map_path = get_issue_map(analyzer_name)
modified_files = get_files_to_analyze(code_path)
run_sarif_parser(
artifacts_path, output_path, issue_map_path, modified_files=modified_files
Expand Down
228 changes: 228 additions & 0 deletions tests/test_community_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,180 @@
"extra_data": {},
}

expected_result_no_issue_map = {
"is_passed": False,
"issues": [
{
"issue_code": "no-read-only-root-fs",
"issue_text": 'container "kube-scheduler" does not have a read-only root file system\nobject: <no namespace>/test-release-kube-scheduler apps/v1, Kind=Deployment',
"location": {
"path": "charts/kube-scheduler/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "run-as-non-root",
"issue_text": 'container "kube-scheduler" is not set to runAsNonRoot\nobject: <no namespace>/test-release-kube-scheduler apps/v1, Kind=Deployment',
"location": {
"path": "charts/kube-scheduler/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "env-var-secret",
"issue_text": 'environment variable TASK_IMAGE_PULL_SECRET_NAME in container "runner" found\nobject: <no namespace>/test-release-runner apps/v1, Kind=Deployment',
"location": {
"path": "charts/runner/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "env-var-secret",
"issue_text": 'environment variable TASK_ARTIFACT_SECRET_NAME in container "runner" found\nobject: <no namespace>/test-release-runner apps/v1, Kind=Deployment',
"location": {
"path": "charts/runner/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "no-read-only-root-fs",
"issue_text": 'container "runner" does not have a read-only root file system\nobject: <no namespace>/test-release-runner apps/v1, Kind=Deployment',
"location": {
"path": "charts/runner/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "run-as-non-root",
"issue_text": 'container "runner" is not set to runAsNonRoot\nobject: <no namespace>/test-release-runner apps/v1, Kind=Deployment',
"location": {
"path": "charts/runner/templates/deployment.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "no-read-only-root-fs",
"issue_text": 'container "runner-rqlite" does not have a read-only root file system\nobject: <no namespace>/test-release-runner-rqlite apps/v1, Kind=StatefulSet',
"location": {
"path": "charts/runner/templates/rqlite-statefulset.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "run-as-non-root",
"issue_text": 'container "runner-rqlite" is not set to runAsNonRoot\nobject: <no namespace>/test-release-runner-rqlite apps/v1, Kind=StatefulSet',
"location": {
"path": "charts/runner/templates/rqlite-statefulset.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "latest-tag",
"issue_text": 'The container "wget" is using an invalid container image, "busybox". Please use images that are not blocked by the `BlockList` criteria : [".*:(latest)$" "^[^:]*$" "(.*/[^:]+)$"]\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "no-read-only-root-fs",
"issue_text": 'container "wget" does not have a read-only root file system\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "run-as-non-root",
"issue_text": 'container "wget" is not set to runAsNonRoot\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "unset-cpu-requirements",
"issue_text": 'container "wget" has cpu request 0\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "unset-cpu-requirements",
"issue_text": 'container "wget" has cpu limit 0\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "unset-memory-requirements",
"issue_text": 'container "wget" has memory request 0\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
{
"issue_code": "unset-memory-requirements",
"issue_text": 'container "wget" has memory limit 0\nobject: <no namespace>/test-release-runner-test-connection /v1, Kind=Pod',
"location": {
"path": "charts/runner/templates/tests/test-connection.yaml",
"position": {
"begin": {"column": 1, "line": 1},
"end": {"column": 1, "line": 1},
},
},
},
],
"errors": [],
"metrics": [],
"extra_data": {},
}


def test_community_analyzer(tmp_path: Path) -> None:
"""Test for `run_community_analyzer.main()`, to test `issue_map.json` parsing."""
Expand Down Expand Up @@ -234,3 +408,57 @@ def test_community_analyzer(tmp_path: Path) -> None:
issue["location"]["path"]
== "charts/runner/templates/tests/test-connection.yaml"
)


def test_community_analyzer_without_issue_map(tmp_path: Path) -> None:
"""Test for `run_community_analyzer.main()` when no analyzer is specified and thus `issue_map.json` is not there."""
code_path = "/code"
toolbox_path = tmp_path.as_posix()
artifacts_path = os.path.join(os.path.dirname(__file__), "test_artifacts")
analysis_config_path = os.path.join(toolbox_path, "analysis_config.json")
modified_files = extract_filepaths_from_deepsource_json(code_path, expected_result)
os.environ["CODE_PATH"] = code_path
os.environ["TOOLBOX_PATH"] = toolbox_path
os.environ["ARTIFACTS_PATH"] = artifacts_path

# Case: when analysis config is not present, it should raise an error.
with pytest.raises(ValueError) as exe:
run_community_analyzer.main()
assert (
str(exe.value) == f"Could not find analysis config at {analysis_config_path}."
)

# Case: all files from the report are present in the analysis config.
with temp_analysis_config(analysis_config_path, modified_files):
run_community_analyzer.main()

analysis_results = tmp_path / "analysis_results.json"
assert analysis_results.exists()

with open(analysis_results) as file:
result = json.load(file)

assert result == expected_result_no_issue_map

# Case: only a subset of files from the report are present in the analysis config.
# Note: There are 7 issues in this file in our report fixture.
# See `expected_result`.
modified_files = [
os.path.join(code_path, "charts/runner/templates/tests/test-connection.yaml"),
]
with temp_analysis_config(analysis_config_path, modified_files):
run_community_analyzer.main()

analysis_results = tmp_path / "analysis_results.json"
assert analysis_results.exists()

with open(analysis_results) as file:
result = json.load(file)

assert len(result["issues"]) == 7

for issue in result["issues"]:
assert (
issue["location"]["path"]
== "charts/runner/templates/tests/test-connection.yaml"
)
Loading