#456 Use 'parent_brew_build' to find parent images
Merged 4 years ago by gnaponie. Opened 4 years ago by gnaponie.
gnaponie/freshmaker FACTORY-4953  into  master

file modified
+75 -74
@@ -182,6 +182,7 @@ 

              "arches": None,

              "odcs_compose_ids": None,

              "published": None,

+             "parent_image_builds": None,

          }

  

      @region.cache_on_arguments()
@@ -214,12 +215,11 @@ 

                          "in the Koji build %r" % build)

  

              # Get the list of ODCS composes used to build the image.

-             if ("extra" in build and

-                     "image" in build["extra"] and

-                     "odcs" in build["extra"]["image"] and

-                     "compose_ids" in build["extra"]["image"]["odcs"]):

-                 data["odcs_compose_ids"] = \

-                     build["extra"]["image"]["odcs"]["compose_ids"]

+             extra_image = build.get("extra", {}).get("image", {})

+             if extra_image.get("odcs", {}).get("compose_ids"):

+                 data["odcs_compose_ids"] = extra_image["odcs"]["compose_ids"]

+ 

+             data["parent_image_builds"] = extra_image.get("parent_image_builds")

  

              brew_task = session.get_task_request(

                  build['task_id'])
@@ -710,6 +710,7 @@ 

              {"field": "repositories.*.repository", "include": True, "recursive": True},

              {"field": "repositories.*.tags.*.name", "include": True, "recursive": True},

              {"field": "content_sets", "include": True, "recursive": True},

+             {"field": "parent_brew_build", "include": True, "recursive": False},

          ]

          if include_rpms:

              if srpm_names:
@@ -945,7 +946,7 @@ 

          return images

  

      def get_images_by_nvrs(self, nvrs, published=True, content_sets=None,

-                            srpm_nvrs=None, include_rpms=True):

+                            srpm_nvrs=None, include_rpms=True, srpm_names=None):

          """Query lightblue and returns containerImages defined by list of

          `nvrs`.

  
@@ -956,6 +957,7 @@ 

          :param list srpm_nvrs: list of SRPM NVRs to look for

          :param bool include_rpms: When True, the rpm_manifest is included in

              the returned ContainerImages.

+         :param list srpm_names: list of SRPM names to look for.

          :return: List of containerImages.

          :rtype: list of ContainerImages.

          """
@@ -1018,6 +1020,17 @@ 

                      "rvalue": published

                  })

  

+         if srpm_names:

+             image_request["query"]["$and"].append(

+                 {

+                     "$or": [{

+                         "field": "rpm_manifest.*.rpms.*.srpm_name",

+                         "op": "=",

+                         "rvalue": srpm_name

+                     } for srpm_name in srpm_names]

+                 }

+             )

+ 

          images = self.find_container_images(image_request)

          if srpm_nvrs is not None:

              images = self.filter_out_images_with_higher_srpm_nvr(images, srpm_name_to_nvrs)
@@ -1064,6 +1077,8 @@ 

              return None

          return images[0]

  

+     # TODO: this should be removed in the future. There's a field in lightblue and koji

+     # that allows us to get the parent directly, without checking the layers.

      @region.cache_on_arguments()

      def get_image_by_layer(self, top_layer, build_layers_count,

                             srpm_name):
@@ -1202,82 +1217,68 @@ 

  

          return latest_parent

  

-     def find_parent_images_with_package(self, child_image, srpm_name, layers):

+     def find_parent_images_with_package(self, child_image, srpm_name, images=None):

          """

-         Returns the chain of all parent images of the image with

-         parsed_data.layers `layers` which contain the package `srpm_name`

-         in their RPM manifest.

+         Returns the chain of all parent images of the image which contain the

+         package `srpm_name` in their RPM manifest.

  

-         The first item in the list is direct parent of the image in question.

+         The first item in the list is the direct parent of the image in question.

          The last item in the list is the top level parent of the image in

          question.

  

-         Docker images are layered and those layers are identified by its

-         checksum in the ContainerImage["parsed_data"]["layers"] list.

-         The first layer defined there is the layer defining the image

-         itself, the second layer is the layer defining its parent, and so on.

- 

-         To find the parent image P of image X, we therefore have to search for

-         an image which has P.parsed_data.layers[0] equal to

-         X.parsed_data.layers[1]. However, query like this is not possible, so

-         we search for any image containing the layer X.parsed_data.layers[1],

-         but further limit the query to return only image which have the count

-         of the layers equal to `build_layers_count`. For example, layers of an

-         image

- 

-         [

-            "sha256:3341bdf...b8e36168", <- layer of this image

-            "sha256:5fc16d0...0e4e587e", <- probably the first parent image A

-            "sha256:5d181d2...e6ad6992",

-            "sha256:274f5cd...ff8fd6e7", <- parent image of parent image A

-            "sha256:3ca89ba...b0ecae0e",

-            "sha256:77ed333...a44a147a",

-            "sha256:e2ec004...4c1fc873"

-         ]

- 

-         Parent images will be retrieved though these layers from top to bottom.

+         This method is recursive.

          """

-         images = []

- 

-         for idx, parent_top_layer in enumerate(layers[1:]):

-             # `len(layers) - 1 - idx`. We decrement 1, because we skip the

-             # first layer in for loop.

-             parent_build_layers_count = len(layers) - 1 - idx

-             image = self.get_image_by_layer(parent_top_layer,

-                                             parent_build_layers_count,

-                                             srpm_name)

-             children = images if images else [child_image]

-             if image:

-                 image.resolve(self, children)

+         if not images:

+             images = []

+         parent_image = None

+ 

+         children = images if images else [child_image]

+         # We first try to find the parent from the `parent_brew_build` field in Lightblue.

+         parent_brew_build = child_image.get("parent_brew_build")

+         # We need to resolve the image in here because "parent_image_builds" needs to be there

+         # and it gets populated when the image gets resolved.

+         child_image.resolve(self, children)

+         # If the parent is not in `parent_brew_build` we can try to look for the parent in Brew,

+         # using the field `parent_image_builds` (searching for the nvr), which should always be there.

+         # In case parent_brew_build is None and child_image["parent_image_builds"] == {},

+         # it means we found a base image, so we'll just continue and return the children.

+         if not parent_brew_build and child_image["parent_image_builds"]:

+             parent_brew_build = [

+                 i["nvr"] for i in child_image["parent_image_builds"].values()

+                 if i["id"] == child_image["parent_build_id"]][0]

+         # We've reached the base image, stop recursion

+         if not parent_brew_build:

+             return children

+         parent_image = self.get_images_by_nvrs([parent_brew_build], srpm_names=[srpm_name])

+ 

+         if parent_image:

+             parent_image = parent_image[0]

+             parent_image.resolve(self, children)

  

-             if images:

-                 if image:

-                     images[-1]['parent'] = image

+         if images:

+             if parent_image:

+                 images[-1]['parent'] = parent_image

+             else:

+                 # If we did not find the parent image with the package,

+                 # we still want to set the parent of the last image with

+                 # the package so we know against which image it has been

+                 # built.

+                 # Let's try first with the "parent_brew_build" field.

+                 parent = self.get_images_by_nvrs([parent_brew_build])

+                 if parent:

+                     parent = parent[0]

+                     parent.resolve(self, images)

                  else:

-                     # If we did not find the parent image with the package,

-                     # We still want to set the parent of the last image with

-                     # the package so we know against which image it has been

-                     # built.

-                     parent = self.find_latest_parent_image(

-                         parent_top_layer, parent_build_layers_count)

- 

-                     children_image_layers_count = parent_build_layers_count + 1

-                     if parent is None and children_image_layers_count != 2:

-                         err = "Cannot find parent of image %s with layer %s " \

-                             "and layer count %d in Lightblue, Lightblue data " \

-                             "is probably incomplete" % (

-                                 children[-1]['brew']['build'], parent_top_layer,

-                               parent_build_layers_count)

-                         log.error(err)

-                         if not images[-1]['error']:

-                             images[-1]['error'] = err

+                     err = "Couldn't find parent image. Lightblue data is probably incomplete"

+                     log.error(err)

+                     if not images[-1]['error']:

+                         images[-1]['error'] = err

+                 images[-1]['parent'] = parent

  

-                     if parent:

-                         parent.resolve(self, images)

-                     images[-1]['parent'] = parent

-             if not image:

-                 return images

-             images.append(image)

+         if not parent_image:

+             return images

+         images.append(parent_image)

+         return self.find_parent_images_with_package(parent_image, srpm_name, images)

  

      def find_images_with_packages_from_content_set(

              self, srpm_nvrs, content_sets, filter_fnc=None, published=True,

file modified
+108 -48
@@ -636,6 +636,7 @@ 

                  },

                  "content_sets": ["dummy-content-set-1",

                                   "dummy-content-set-2"],

+                 'parent_brew_build': 'some-original-nvr-7.6-252.1561619826',

                  'repositories': [

                      {'repository': 'product1/repo1', 'published': True,

                       'tags': [{"name": "latest"}]}
@@ -776,6 +777,44 @@ 

              },

          ]

  

+         self.fake_images_with_parent_brew_build = [

+             {

+                 'brew': {

+                     'completion_date': '20170421T04:27:51.000-0400',

+                     'build': 'package-name-1-4-12.10',

+                     'package': 'package-name-1'

+                 },

+                 'content_sets': ['dummy-content-set-1',

+                                  'dummy-content-set-2'],

+                 'parent_brew_build': 'some-original-nvr-7.6-252.1561619826',

+                 'repositories': [

+                     {'repository': 'product1/repo1', 'published': True,

+                      'tags': [{'name': 'latest'}]}

+                 ],

+                 'parsed_data': {

+                     'files': [

+                         {

+                             'key': 'buildfile',

+                             'content_url': 'http://git.repo.com/cgit/rpms/repo-1/plain/Dockerfile?id=commit_hash1',

+                             'filename': 'Dockerfile'

+                         }

+                     ],

+                 },

+                 'rpm_manifest': [{

+                     'rpms': [

+                         {

+                             'srpm_name': 'openssl',

+                             'srpm_nevra': 'openssl-0:1.2.3-1.src'

+                         },

+                         {

+                             'srpm_name': 'tespackage',

+                             'srpm_nevra': 'testpackage-10:1.2.3-1.src'

+                         }

+                     ]

+                 }]

+             }

+         ]

+ 

          self.fake_container_images = [

              ContainerImage.create(data)

              for data in self.fake_images_with_parsed_data]
@@ -788,6 +827,10 @@ 

              ContainerImage.create(data)

              for data in self.fake_images_with_modules]

  

+         self.fake_container_images_with_parent_brew_build = [

+             ContainerImage.create(data)

+             for data in self.fake_images_with_parent_brew_build]

+ 

          self.fake_koji_builds = [{"task_id": 654321}, {"task_id": 123456}]

          self.fake_koji_task_requests = [

              ["git://pkgs.devel.redhat.com/rpms/repo-2#commit_hash2",
@@ -1218,6 +1261,7 @@ 

                                   "error": None,

                                   "arches": None,

                                   "odcs_compose_ids": None,

+                                  "parent_image_builds": None,

                                   "published": True,

                                   "brew": {

                                       "completion_date": u"20170421T04:27:51.000-0400",
@@ -1317,58 +1361,13 @@ 

                         cert=self.fake_cert_file,

                         private_key=self.fake_private_key)

          ret = lb.find_parent_images_with_package(

-             self.fake_container_images[0], "openssl",

-             ["layer0", "layer1", "layer2", "layer3"])

+             self.fake_container_images[0], "openssl")

  

          self.assertEqual(1, len(ret))

          self.assertEqual(ret[0]["brew"]["package"], "package-name-1")

          self.assertEqual(set(ret[0]["content_sets"]),

                           set(["dummy-content-set-1", "dummy-content-set-2"]))

  

-     @patch('freshmaker.lightblue.LightBlue.find_container_images')

-     @patch('os.path.exists')

-     def test_parent_images_no_rpm_manifest(self, exists, cont_images):

-         exists.return_value = True

-         images_without_rpm_manifest = []

-         for data in self.fake_images_with_parsed_data:

-             img = ContainerImage.create(data)

-             del img["rpm_manifest"]

-             images_without_rpm_manifest.append(img)

- 

-         cont_images.side_effect = [images_without_rpm_manifest, [],

-                                    images_without_rpm_manifest]

- 

-         lb = LightBlue(server_url=self.fake_server_url,

-                        cert=self.fake_cert_file,

-                        private_key=self.fake_private_key)

-         ret = lb.find_parent_images_with_package(

-             self.fake_container_images[0], "openssl",

-             ["layer0", "layer1", "layer2", "layer3"])

- 

-         self.assertEqual(0, len(ret))

- 

-     @patch('freshmaker.lightblue.LightBlue.find_container_images')

-     @patch('os.path.exists')

-     def test_parent_images_empty_rpm_manifest(self, exists, cont_images):

-         exists.return_value = True

-         images_without_rpm_manifest = []

-         for data in self.fake_images_with_parsed_data:

-             img = ContainerImage.create(data)

-             img["rpm_manifest"] = []

-             images_without_rpm_manifest.append(img)

- 

-         cont_images.side_effect = [images_without_rpm_manifest, [],

-                                    images_without_rpm_manifest]

- 

-         lb = LightBlue(server_url=self.fake_server_url,

-                        cert=self.fake_cert_file,

-                        private_key=self.fake_private_key)

-         ret = lb.find_parent_images_with_package(

-             self.fake_container_images[0], "openssl",

-             ["layer0", "layer1", "layer2", "layer3"])

- 

-         self.assertEqual(0, len(ret))

- 

      @patch('freshmaker.lightblue.ContainerImage.resolve_published')

      @patch('freshmaker.lightblue.LightBlue.find_container_images')

      @patch('os.path.exists')
@@ -1399,8 +1398,7 @@ 

                         cert=self.fake_cert_file,

                         private_key=self.fake_private_key)

          ret = lb.find_parent_images_with_package(

-             self.fake_container_images[0], "openssl",

-             ["layer0", "layer1", "layer2", "layer3", "layer4"])

+             self.fake_container_images[0], "openssl", [])

  

          self.assertEqual(3, len(ret))

          self.assertEqual(ret[0]["brew"]["package"], "package-name-1")
@@ -1596,6 +1594,67 @@ 

                      self.assertTrue(leaf_image6_as_parent["directly_affected"])

                      break

  

+     @patch("freshmaker.lightblue.ContainerImage.resolve_published")

+     @patch("freshmaker.lightblue.LightBlue.get_images_by_nvrs")

+     @patch("os.path.exists")

+     @patch("freshmaker.kojiservice.KojiService.get_build")

+     @patch("freshmaker.kojiservice.KojiService.get_task_request")

+     def test_parent_images_with_package_using_field_parent_brew_build(

+             self, get_task_request, get_build, exists, cont_images,

+             resolve_published):

+         get_build.return_value = {"task_id": 123456}

+         get_task_request.return_value = [

+             "git://example.com/rpms/repo-1#commit_hash1", "target1", {}]

+         exists.return_value = True

+ 

+         cont_images.side_effect = [self.fake_container_images_with_parent_brew_build, [], []]

+ 

+         lb = LightBlue(server_url=self.fake_server_url,

+                        cert=self.fake_cert_file,

+                        private_key=self.fake_private_key)

+         ret = lb.find_parent_images_with_package(

+             self.fake_container_images_with_parent_brew_build[0], "openssl", [])

+ 

+         self.assertEqual(1, len(ret))

+         self.assertEqual(ret[0]["brew"]["package"], "package-name-1")

+         self.assertEqual(set(ret[0]["content_sets"]),

+                          set(["dummy-content-set-1", "dummy-content-set-2"]))

+         self.assertEqual(ret[-1]['error'], "Couldn't find parent image. Lightblue data is probably incomplete")

+ 

+     @patch("freshmaker.lightblue.ContainerImage.resolve_published")

+     @patch("freshmaker.lightblue.LightBlue.get_images_by_nvrs")

+     @patch("os.path.exists")

+     @patch("freshmaker.kojiservice.KojiService.get_build")

+     @patch("freshmaker.kojiservice.KojiService.get_task_request")

+     def test_parent_images_with_package_using_field_parent_image_builds(

+             self, get_task_request, get_build, exists, cont_images,

+             resolve_published):

+         get_build.return_value = {

+             "task_id": 123456,

+             "parent_build_id": 1074147,

+             "parent_image_builds": {

+                 "rh-osbs/openshift-golang-builder:1.11": {

+                     "id": 969696, "nvr": "openshift-golang-builder-container-v1.11.13-3.1"},

+                 "rh-osbs/openshift-ose-base:v4.1.34.20200131.033116": {

+                     "id": 1074147, "nvr": "openshift-enterprise-base-container-v4.1.34-202001310309"}}}

+         get_task_request.return_value = [

+             "git://example.com/rpms/repo-1#commit_hash1", "target1", {}]

+         exists.return_value = True

+ 

+         self.fake_container_images[0].pop('parent_brew_build')

+         cont_images.side_effect = [self.fake_container_images, [], []]

+ 

+         lb = LightBlue(server_url=self.fake_server_url,

+                        cert=self.fake_cert_file,

+                        private_key=self.fake_private_key)

+         ret = lb.find_parent_images_with_package(

+             self.fake_container_images[0], "openssl", [])

+ 

+         self.assertEqual(1, len(ret))

+         self.assertEqual(ret[0]["brew"]["package"], "package-name-1")

+         self.assertEqual(set(ret[0]["content_sets"]),

+                          set(["dummy-content-set-1", "dummy-content-set-2"]))

+ 

      @patch('freshmaker.lightblue.LightBlue.find_images_with_packages_from_content_set')

      @patch('freshmaker.lightblue.LightBlue.find_unpublished_image_for_build')

      @patch('os.path.exists')
@@ -1693,6 +1752,7 @@ 

                              {'field': 'repositories.*.repository', 'include': True, 'recursive': True},

                              {'field': 'repositories.*.tags.*.name', 'include': True, 'recursive': True},

                              {'field': 'content_sets', 'include': True, 'recursive': True},

+                             {'field': 'parent_brew_build', 'include': True, 'recursive': False},

                              {'field': 'rpm_manifest.*.rpms', 'include': True, 'recursive': True},

                              {'field': 'rpm_manifest.*.rpms.*.srpm_name', 'include': True, 'recursive': True}],

               'objectType': 'containerImage'})

In Lightblue there are currently 2 variants of same image. One is
published and the other is not. Freshmaker uses both to find parent
image tree. There is already new field 'parent_brew_build' which
could be used instead.
Old behavior kept for the moment for backwards compatibility.

JIRA: FACTORY-4953

Signed-off-by: Giulia Naponiello gnaponie@redhat.com

Couldn't get the image with the NVR - parent_brew_build missing => Couldn't directly get the parent image NVR because "parent_brew_build" is missing

What if this is the parent image? Then parent_brew_build will be None and it will cause this to be logged. I think you need to log this only if parent_brew_build is not set and a parent image was found using the old approach.

Depending on how Lightblue works, maybe it's possible only to check for the presence of the parent_brew_build key (not the value). If an old container build doesn't have the key set even when you request the field in your query, then this approach would work.

Edit:
Maybe you could also check if parent_brew_buildis None but layers has more than one entry.

Won't this only contain the child image's immediate parent? You need to find all the parent images of the child.

How do you know the parent image contains the package?

I'm not sure, but I don't think recursive is necessary here. I'd try without it.

log.warning("Couldn't get the image with the NVR - parent_brew_build missing "

My suggestion for this log message is: Couldn't get parent images due to missing child image's parent_brew_build. Fallback to original behavior to get the parent images.

The major thought is the log should tell what didn't succeed and what has to do next to get the parent images. The latter does not involve technical details.

@gnaponie, I think you are right here. You need to check that the parent image returned by the get_images_by_nvrs contains the srpm_name. The get_images_by_nvrs method can almost do that - it accepts srpm_nvr, gets srpm_name from that and uses that as filter in lightblue query. You might just change it slightly to support srpm_name too.

You also need to get the parent image of that parent image and also check if it contains the srpm_name. If it does, you need to check parent of parent of parent image, ... until you a) find the base image which has no other parents or b) find an image which does not contain srpm_name.

The old code does the same, so you can check it for more info :).

rebased onto 005b7bd5ee750a62e96a47c4dec341efeb0ba61d

4 years ago

@jkaluza @mprahl @cqi @lucarval
Can you please review once again? Thanks.

rebased onto 39b0c487a73a8cc64e064c14f6e84b620fcf1485

4 years ago

Optional: How about if srpm_names:?

Could you update the docstring? It only discusses the old approach of querying by the number of layers.

Also, it's nice to document when a function is recursive.

Won't this warning be logged if child_image is a base image? Before logging this, you'll need to verify that this image has more than two layers, which indicates it is not a base image.

Could you keep the comment that was removed explaining this?

It's possible that parent_brew_build is set, but the parent just didn't include the affected SRPM. I'd suggest using that before falling back to this approach. It's guaranteed to be accurate and it'll be faster.

Optional: Instead of backslashes, I find it's cleaner use parentheses. For example:

err = (
    "Cannot find parent of image %s with layer %s "
    "and layer count %d in Lightblue, Lightblue data "
    "is probably incomplete"
    % (children[-1]['brew']['build'], parent_top_layer, parent_build_layers_count)
)

Some of the strings are unicode, while others aren't. Since this is a Python 3 project, I suggest making them normal strings.

Yeah... I just copied from the previous ones. I'll just change them all.

This was copy pasted from another variable. I'll change in this PR this one, but we'll have to make a separate commit for the other ones.

I'm not sure I understand this comment. Can you explain better?
First it tries to get it with "parent_brew_build". If the field is not there it tries by layer.
Then if no image is found it ends up here.

rebased onto a7f580c9246fc2f71121f3a1b2c405bae9cb2428

4 years ago

There is an extra space :)

Could you reword Here described this lates behaviour? I don't quite understand what you mean.

The srpm_names value doesn't look right to me. Isn't child_image['parent_brew_build'] the child image's parent container image and not an SRPM? If I misunderstood, could you please explain?

My point in the last review was that if child_image has parent_brew_build set, it's possible that image is None because the parent image didn't have the SRPM. In this case, you should check to see if parent_brew_build is set, and if so, use get_images_by_nvrs on that value without the SRPM filter.

Also, the first argument to get_images_by_nvrs should be child_image['parent_brew_build'] since image is actually the parent of child_image. It might make it easier to understand if theimage variable somehow mentioned that it was the parent.

From the line if parent is None and children_image_layers_count != 2: below, it insinuates that all base images have two layers, so if len(layers) >= 2: would be True if child_image is a base image. This then causes this warning to be logged which isn't desired.

I would verify this is always the case though.

The point was that the description that follows is the one regarding the latest explained behaviour (by layers).
lates --> latest (typo). I'll try to reword.

Also, the first argument to get_images_by_nvrs should be child_image['parent_brew_build'] since image is actually the parent of child_image. It might make it easier to understand if theimage variable somehow mentioned that it was the parent.

I think you are right. I'm really getting confused by the names... Thinking out loud:
child_image is the current image. child_image['parent_brew_build'] contains the NVR of the parent of the current image. So we need to call get_images_by_nvr to get the actual image object from that NVR.

Mmm this in my mind was another case. But I'm afraid I've confused the logic.
In my mind len(layers) >= 2 emulated the for loop, that skips the first layer for idx, parent_top_layer in enumerate(layers[1:]):, and doesn't refer to if parent is None and children_image_layers_count != 2: which is later, and it wasn't removed/changed...
But I'm afraid this if condition here is wrong, because it wouldn't make sense after the first recursive call.

...or maybe that's ok because layer always remains the same through iterations.

rebased onto 52ff977bbe3069f92b60d9637a21ded1fa553d8a

4 years ago

@mprahl Addressed the comments. Could you review once again? Thank you

Optional: None is not needed here.

I find the variable name misleading. "top" implies the last layer, but it's actually the parent layer of child_image.

One way to simplify this method is by removing the counter property. You can do this by shortening the layers property for every recursive call. For instance:

return self.find_parent_images_with_package(image, srpm_name, layers[1:], images)

With this approach, layers is always just the layers of the input child_image. In my opinion, this is a lot easier to read.

Optional: None is not needed here.

Optional: Could you rename this to parent_image? I think it makes it a lot easier to read.

Optional: What do you think about renaming images to child_image_children? It makes it clear what this list is.

This will be incorrectly logged when child_image is a parent image without the specified SRPM, since in this case, image is always None and child_image['parent_brew_build'] is not set.

You can refactor if parent is None and children_image_layers_count != 2: to have one if statement of if children_image_layers_count != 2: that logs this. Then you can nest an additional if statement of if parent is None and log "Cannot find parent..." as you do currently.

I think you need to check if parent_build_layers_count > 1:. layers in this current implementation includes all the layers, even ones that were previously processed higher up in the call stack.

Since the existing logic to detect if something was not a parent image was children_image_layers_count != 2, this would mean the equivalent logic is parent_build_layers_count != 1. This is because children_image_layers_count = parent_build_layers_count + 1.

On second thought, is this log statement even necessary? The similar log statement in the beginning of the method should handle all cases.

rebased onto b65663facb709c60398486fa027203ca93758aca

4 years ago

@mprahl can you review again? Thank you.

You may want to have an else branch that logs an error since if parent is None, it's due to incomplete lightblue data.

If you want to keep the same behavior as before, you need to unindent these two lines. This is also to make it consistent with the else branch of if parent_image: below, since you search for the parent regardless of the layer count.

I know this behavior preexisted this PR, but I find it strange to resolve all of child_image_children since child_image_children contains images that were individually resolved in previous calls of this method on the call stack.

Optional: It'd be nice consistent with your usage of single quotes vs double quotes. For instance, your patch decorators use single quotes but the method body uses double quotes.

Rather than patching this, it might make sense to patch get_images_by_nvrs so you can verify it was properly called based on the presence of the "parent_brew_build" key.

I find it strange that you're calling find_parent_images_with_package with self.fake_container_images_with_parent_brew_build[0] and having its parent end up being itself.

This unfortunately is inconsistent through the whole project. We should make an effort with future PRs to fix that.

Not sure if there's some issue with the test suite. But this seems like the expected behaviour for similar tests in the same file too. Example I was checking test_parent_images_with_package.

rebased onto dfebf88c068c7bcf302509f0207589e92750eb7c

4 years ago

@mprahl I've address the comments again.
I appreciate the reviews, but I've been already asked twice to please speed up the release of this change. So if there aren't big issues with this PR I would move forward and merge it. Can you please review it once more, and in case there's no blocking merge it? For non-blocking change requests we can follow with other PRs.

This comment is now out of date.

:thumbsup: from me, though my comments about the test still stands. Additionally, you're missing a test for when the parent image doesn't include the RPM but is in lightblue. I'll leave it up to you if you want to address that or not.

rebased onto fe0e9bb494ca0b052925befd0a49be6b575ba57c

4 years ago

rebased onto 056183c638f3f3d65ae2604fb2aef1b030345f26

4 years ago

Made some changes based on the face to face discussion and added some tests.

rebased onto 7c0f874c8411f11507577c83aac66de1ec33f4bf

4 years ago

rebased onto e26ee8f9fdf138900b50a3d9368270299dd70ff3

4 years ago

rebased onto d2e47cce381b1bdd8751670ee81399405ca74017

4 years ago

The first arg must be a list, so [parent_brew_build].

The first arg must be a list, so [parent_brew_build].

What if there are multiple entries in parent_image_builds? Or what if there aren't any as in the case of base images?

It's not clear to me when this is actually done.

rebased onto d224915b81c4347b0d2e98c835855718f6fdb188

4 years ago

1 new commit added

  • torebase
4 years ago

rebased onto 4d04b99

4 years ago

:+1: makes sense to me!

Commit 8876bd0 fixes this pull-request

Pull-Request has been merged by gnaponie

4 years ago

Pull-Request has been merged by gnaponie

4 years ago