Repository: cekit/cekit

Issue:
Dependency Handling with descriptor reference
This is a sequel to #696 / #701 ; if we instead we modify builder.py :: before_generate (L81) so that init is called _before_ `dependency_handler.handle` then we could pass the descriptor reference to the static `dependencies` method thereby allowing it to check for content sets and determine whether to require the odcs dependency.

Notes from discussion: External code https://github.com/cekit/behave-test-steps/blob/v1/loader.py requires similar parameters so we can't change the number of parameters. It might be possible to overload the params, perhaps using `params.image....repo... `and check for content_sets. 

Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/cekit/cekit/pull/893?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cekit) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 89.96%. Comparing base [(`4b6aaad`)](https://app.codecov.io/gh/cekit/cekit/commit/4b6aaad599526f3095dbe600ba9284ea6cce7549?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cekit) to head [(`74298d1`)](https://app.codecov.io/gh/cekit/cekit/pull/893?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cekit).
> Report is 9 commits behind head on develop.


<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           develop     #893      +/-   ##
===========================================
- Coverage    90.16%   89.96%   -0.20%     
===========================================
  Files           42       42              
  Lines         3263     3230      -33     
===========================================
- Hits          2942     2906      -36     
- Misses         321      324       +3     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/cekit/cekit/pull/893?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cekit).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cekit).


Patch:
diff --git a/Pipfile b/Pipfile
index 7d174a8..b24d716 100644
--- a/Pipfile
+++ b/Pipfile
@@ -19,6 +19,7 @@ autopep8 = "*"
 isort = "*"
 black = "*"
 flake8 = ">3.6.0"
+"odcs[client]" = ">=0.2.10"
 
 [packages]
 pykwalify = ">=1.6.0"
@@ -26,7 +27,6 @@ colorlog = ">=2.10.0"
 PyYAML = ">=3.10"
 Jinja2 = ">=2.7"
 click = ">=6.7"
-"odcs[client]" = ">=0.2.10"
 "ruamel.yaml" = {version="<=0.18.3",python_version="<3.7"}
 
 [requires]
diff --git a/cekit/builder.py b/cekit/builder.py
index c478f7f..eef7bea 100644
--- a/cekit/builder.py
+++ b/cekit/builder.py
@@ -111,12 +111,12 @@ class Builder(Command):
             self.generator.add_redhat_overrides()
 
     def before_generate(self) -> None:
-        # Handle dependencies for selected generator, if any
+        self.generator.init()
+
         LOGGER.debug("Checking CEKit generate dependencies...")
+        # Handle dependencies for selected generator, if any
         self.dependency_handler.handle(self.generator, self.params)
 
-        self.generator.init()
-
     def generate(self) -> None:
         self.generator.generate()
 
diff --git a/cekit/generator/base.py b/cekit/generator/base.py
index c38b0a9..8e65ace 100644
--- a/cekit/generator/base.py
+++ b/cekit/generator/base.py
@@ -106,13 +106,15 @@ class Generator(object):
         LOGGER.info("Initializing image descriptor...")
 
     @staticmethod
-    def dependencies(params: Map = None) -> DependencyDefinition:
+    def dependencies(params: Map = None, image: Image = None) -> DependencyDefinition:
         deps = {}
 
-        deps["odcs-client"] = {
-            "package": "python3-odcs-client",
-            "library": "odcs",
-        }
+        # Only activate dependency requirement for odcs if we have content_sets
+        if image and image.get("packages").get("content_sets"):
+            deps["odcs-client"] = {
+                "package": "python3-odcs-client",
+                "library": "odcs",
+            }
 
         if CONFIG.get("common", "redhat"):
             deps["brew"] = {"package": "brewkoji", "executable": "brew"}
diff --git a/cekit/tools.py b/cekit/tools.py
index 9fb41d0..2f851e6 100644
--- a/cekit/tools.py
+++ b/cekit/tools.py
@@ -647,18 +647,11 @@ class DependencyHandler(object):
         if not o:
             return
 
-        # Get the class of the object
-        clazz = type(o)
+        if callable(getattr(o, "dependencies", None)):
+            from cekit.generator.base import Generator
 
-        for var in [clazz, o]:
-            # Check if a static method or variable 'dependencies' exists
-            dependencies = getattr(var, "dependencies", None)
-
-            if not dependencies:
-                continue
-
-            # Check if we have a method
-            if callable(dependencies):
-                # Execute that method to get list of dependencies and try to handle them
+            # Execute that method to get list of dependencies and try to handle them
+            if isinstance(o, Generator):
+                self._handle_dependencies(o.dependencies(params, o.image))
+            else:
                 self._handle_dependencies(o.dependencies(params))
-                return
diff --git a/requirements.txt b/requirements.txt
index b4fe552..541d27f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,5 +13,4 @@ pykwalify>=1.6.0
 colorlog>=2.10.0
 click>=6.7
 packaging>=19.0
-odcs[client]>=0.2.10
 ruamel.yaml<=0.18.3 ; python_version<'3.7'


Test patch:
diff --git a/tests/test_validate.py b/tests/test_validate.py
index f638d56..539dcfb 100644
--- a/tests/test_validate.py
+++ b/tests/test_validate.py
@@ -179,8 +179,6 @@ def test_content_sets_file_container_embedded(tmpdir, mocker, caplog):
 
 
 def test_content_sets_embedded_container_embedded(tmpdir, mocker, caplog):
-    # Do not try to validate dependencies while running tests, these are not necessary
-    mocker.patch("cekit.generator.docker.DockerGenerator.dependencies").return_value({})
     mocker.patch("odcs.client.odcs.ODCS.new_compose", return_value={"id": 12})
     mocker.patch(
         "odcs.client.odcs.ODCS.wait_for_compose",
@@ -196,6 +194,10 @@ def test_content_sets_embedded_container_embedded(tmpdir, mocker, caplog):
 
     run_cekit_cs_overrides(image_dir, mocker, overrides_descriptor)
 
+    assert (
+        "Required CEKit library 'odcs-client' was found as a 'odcs' module!"
+        in caplog.text
+    )
     assert (
         "Requesting ODCS pulp compose for 'aaa bbb' repositories with '[]' flags..."
         in caplog.text
@@ -1339,7 +1341,7 @@ def test_package_related_commands_packages_in_module(tmpdir, mocker):
     regex_dockerfile(image_dir, "rm -rf.*/var/cache/yum")
 
 
-def test_package_related_commands_packages_in_image(tmpdir, mocker):
+def test_package_related_commands_packages_in_image(tmpdir, caplog):
     image_dir = str(tmpdir.mkdir("source"))
     copy_repos(image_dir)
 
@@ -1349,7 +1351,17 @@ def test_package_related_commands_packages_in_image(tmpdir, mocker):
     with open(os.path.join(image_dir, "image.yaml"), "w") as fd:
         yaml.dump(img_desc, fd, default_flow_style=False)
 
-    run_cekit(image_dir)
+    run_cekit(
+        image_dir,
+        parameters=[
+            "-v",
+            "build",
+            "--dry-run",
+            "--container-file",
+            "Dockerfile",
+            "podman",
+        ],
+    )
 
     expected_packages_install = """
         USER root
@@ -1358,6 +1370,10 @@ def test_package_related_commands_packages_in_image(tmpdir, mocker):
             && rpm -q wget mc
 """
 
+    assert (
+        "Required CEKit library 'odcs-client' was found as a 'odcs' module!"
+        not in caplog.text
+    )
     assert check_dockerfile_text(image_dir, expected_packages_install)