Skip to content

Commit bef34de

Browse files
committed
Add static check for NetworkPolicy presence
A new static check for all incoming bundles that rejects any bundle that contains a NetworkPolicy. Based on the decision from OLM team this resource is temporarily not allowed globally for all OCP versions until OLM releases a backport. JIRA: ISV-6226 Signed-off-by: Ales Raszka <araszka@redhat.com>
1 parent 3e38db0 commit bef34de

5 files changed

Lines changed: 153 additions & 1 deletion

File tree

docs/users/static_checks.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,19 @@ To prevent the test from failing download the latest [Makefile](https://raw.gith
173173
and re-render the catalog again with `make catalogs` command. The Makefile uses
174174
extra arguments `--migrate-level bundle-object-to-csv-metadata` for opm when rendering
175175
catalogs for `>=4.17` version.
176+
177+
#### check_network_policy_presence
178+
179+
The test checks if there is a NetworkPolicy object defined in the bundle manifests.
180+
```yamlyaml
181+
apiVersion: networking.k8s.io/v1
182+
kind: NetworkPolicy
183+
...
184+
```
185+
186+
The NetworkPolicy resource are not supported in the OpenShift and static checks
187+
will raise an error if such resource is found in the bundle manifests.
188+
176189
## Running tests locally
177190

178191
```bash

operator-pipeline-images/operatorcert/operator_repo/core.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# pylint: disable=too-many-lines
12
"""
23
Definition of Repo, Operator, Bundle, Catalog and CatalogOperator classes
34
"""
@@ -7,7 +8,7 @@
78
from dataclasses import dataclass
89
from functools import cached_property, total_ordering
910
from pathlib import Path
10-
from typing import Any, Optional, SupportsIndex, Union
11+
from typing import Any, Optional, SupportsIndex, Union, Generator
1112

1213
from semantic_version import NpmSpec, Version
1314

@@ -179,6 +180,36 @@ def csv_file_name(self) -> Path:
179180
f"CSV file for {self.operator_name}/{self.operator_version} not found"
180181
)
181182

183+
def manifest_files(self) -> list[Path]:
184+
"""
185+
Get a list of all manifest files in the bundle.
186+
The manifest files are considered to be all .yaml and .yml files within
187+
the manifests/ directory of the bundle.
188+
189+
Returns:
190+
list[Path]: List of paths to manifest files.
191+
"""
192+
return list(self._manifests_path.glob("*.yaml")) + list(
193+
self._manifests_path.glob("*.yml")
194+
)
195+
196+
def manifest_files_content(
197+
self,
198+
) -> Generator[tuple[Path, dict[str, Any]], None, None]:
199+
"""
200+
Iterate over all manifest files in the bundle and yield their content.
201+
202+
Yields:
203+
Generator[tuple[Path, dict[str, Any]], None, None]: A generator yielding tuples
204+
with the file path and its parsed content as a dictionary.
205+
"""
206+
for file in self.manifest_files():
207+
content = load_yaml(file)
208+
if not isinstance(content, dict):
209+
log.warning("Manifest file %s does not contain a valid yaml document")
210+
continue
211+
yield file, content
212+
182213
@property
183214
def channels(self) -> set[str]:
184215
"""

operator-pipeline-images/operatorcert/static_tests/common/bundle.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,25 @@ def check_validate_schema_bundle_release_config(
187187
"Bundle's 'release-config.yaml' contains invalid data "
188188
f"which does not comply with the schema: {ve.message}"
189189
)
190+
191+
192+
def check_network_policy_presence(bundle: Bundle) -> Iterator[CheckResult]:
193+
"""
194+
Check if the bundle contains a network policy object within its manifests.
195+
Network policies are not supported by OpenShift and their presence
196+
in the bundle will lead to bundle rejection during the certification process.
197+
"""
198+
for manifest_file, content in bundle.manifest_files_content():
199+
kind = content.get("kind") or ""
200+
api_version = content.get("apiVersion") or ""
201+
202+
if not (
203+
kind == "NetworkPolicy" and api_version.startswith("networking.k8s.io/")
204+
):
205+
continue
206+
207+
yield Fail(
208+
f"Bundle contains a NetworkPolicy in {manifest_file.name}. "
209+
"Network policies are not a supported resource that Operator "
210+
"Lifecycle Manager(OLM) can install and manage."
211+
)

operator-pipeline-images/tests/operator_repo/test_bundle.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,38 @@ def test_bundle_invalid(tmp_path: Path) -> None:
142142
def test_bundle_caching(mock_bundle: Bundle) -> None:
143143
assert Bundle(mock_bundle.root).operator == mock_bundle.operator
144144
assert Bundle(mock_bundle.root).operator is not mock_bundle.operator
145+
146+
147+
def test_bundle_manifest_files(tmp_path: Path) -> None:
148+
create_files(
149+
tmp_path,
150+
bundle_files("hello", "0.0.1"),
151+
{
152+
"operators/hello/0.0.1/manifests/sample_doc.yaml": "---",
153+
"operators/hello/0.0.1/manifests/sample_doc_2.yml": "---\nfoo: bar",
154+
},
155+
)
156+
repo = Repo(tmp_path)
157+
operator = repo.operator("hello")
158+
bundle = operator.bundle("0.0.1")
159+
160+
manifest_files = list(bundle.manifest_files())
161+
assert len(manifest_files) == 3
162+
assert sorted(manifest_files) == sorted(
163+
[
164+
bundle.root / "manifests" / "hello.clusterserviceversion.yaml",
165+
bundle.root / "manifests" / "sample_doc.yaml",
166+
bundle.root / "manifests" / "sample_doc_2.yml",
167+
]
168+
)
169+
for manifest_file, content in bundle.manifest_files_content():
170+
assert manifest_file in manifest_files
171+
assert isinstance(content, dict)
172+
if manifest_file.name == "sample_doc.yaml":
173+
assert content == {}
174+
elif manifest_file.name == "sample_doc_2.yml":
175+
assert content == {"foo": "bar"}
176+
elif manifest_file.name == "hello.clusterserviceversion.yaml":
177+
assert content["metadata"]["name"] == "hello.v0.0.1"
178+
else:
179+
pytest.fail(f"Unexpected manifest file {manifest_file}")

operator-pipeline-images/tests/static_tests/common/test_bundle.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
check_bundle_release_config,
99
check_operator_name,
1010
check_validate_schema_bundle_release_config,
11+
check_network_policy_presence,
1112
)
1213
from tests.utils import bundle_files, create_files
1314

@@ -656,3 +657,53 @@ def test_check_validate_schema_bundle_release_config(
656657
(x.__class__, x.reason)
657658
for x in check_validate_schema_bundle_release_config(bundle)
658659
} == expected_results
660+
661+
662+
@pytest.mark.parametrize(
663+
"files, bundle_to_check, expected_results",
664+
[
665+
pytest.param(
666+
[
667+
bundle_files("hello", "0.0.1"),
668+
],
669+
("hello", "0.0.1"),
670+
set(),
671+
id="pass: network policy not present",
672+
),
673+
pytest.param(
674+
[
675+
bundle_files("hello", "0.0.1"),
676+
{
677+
"operators/hello/0.0.1/manifests/dummy_.k8s.io_v1_networkpolicy.yaml": {
678+
"kind": "NetworkPolicy",
679+
"apiVersion": "networking.k8s.io/v1",
680+
}
681+
},
682+
],
683+
("hello", "0.0.1"),
684+
{
685+
(
686+
Fail,
687+
f"Bundle contains a NetworkPolicy in dummy_.k8s.io_v1_networkpolicy.yaml. "
688+
"Network policies are not a supported resource that Operator "
689+
"Lifecycle Manager(OLM) can install and manage.",
690+
),
691+
},
692+
id="fail: A bundle contains a NetworkPolicy",
693+
),
694+
],
695+
)
696+
def test_check_network_policy_presence(
697+
tmp_path: Path,
698+
files: list[dict[str, Any]],
699+
bundle_to_check: tuple[str, str],
700+
expected_results: set[tuple[type, str]],
701+
) -> None:
702+
create_files(tmp_path, *files)
703+
repo = Repo(tmp_path)
704+
operator_name, bundle_version = bundle_to_check
705+
operator = repo.operator(operator_name)
706+
bundle = operator.bundle(bundle_version)
707+
assert {
708+
(x.__class__, x.reason) for x in check_network_policy_presence(bundle)
709+
} == expected_results

0 commit comments

Comments
 (0)