#360 Add `internal.UpdateDBOnODCSComposeFail` handler to mark ArtifactBuilds as failed in case of ODCS compose failure.
Merged 9 months ago by jkaluza. Opened 9 months ago by jkaluza.
jkaluza/freshmaker odcs-compose-error-msg  into  master

@@ -22,3 +22,4 @@ 

  from .update_db_on_advisory_change import UpdateDBOnAdvisoryChange  # noqa

  from .update_db_on_module_build import UpdateDBOnModuleBuild  # noqa

  from .generate_advisory_signed_event_on_rpm_sign import GenerateAdvisorySignedEventOnRPMSign  # noqa

+ from .update_db_on_odcs_compose_fail import UpdateDBOnODCSComposeFail  # noqa

@@ -0,0 +1,56 @@ 

+ # -*- coding: utf-8 -*-

+ # Copyright (c) 2017  Red Hat, Inc.

+ #

+ # Permission is hereby granted, free of charge, to any person obtaining a copy

+ # of this software and associated documentation files (the "Software"), to deal

+ # in the Software without restriction, including without limitation the rights

+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ # copies of the Software, and to permit persons to whom the Software is

+ # furnished to do so, subject to the following conditions:

+ #

+ # The above copyright notice and this permission notice shall be included in all

+ # copies or substantial portions of the Software.

+ #

+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

+ # SOFTWARE.

+ 

+ from freshmaker import db

+ from freshmaker.events import ODCSComposeStateChangeEvent

+ from freshmaker.models import ArtifactBuild, ArtifactBuildCompose, Compose

+ from freshmaker.handlers import BaseHandler, fail_event_on_handler_exception

+ from freshmaker.types import ArtifactBuildState

+ from odcs.common.types import COMPOSE_STATES

+ 

+ 

+ class UpdateDBOnODCSComposeFail(BaseHandler):

+     """

+     Marks the ArtifactBuild as FAILED in case the ODCS compose on which the

+     ArtifactBuild depends is moved to "failed" state.

+     """

+ 

+     name = "UpdateDBOnODCSComposeFail"

+     order = 0

+ 

+     def can_handle(self, event):

+         if not isinstance(event, ODCSComposeStateChangeEvent):

+             return False

+         return event.compose["state"] == COMPOSE_STATES["failed"]

+ 

+     @fail_event_on_handler_exception

+     def handle(self, event):

+         # Get all the builds waiting for this compose.

+         builds_with_compose = db.session.query(ArtifactBuild).join(

+             ArtifactBuildCompose).join(Compose)

+         builds_with_compose = builds_with_compose.filter(

+             Compose.odcs_compose_id == event.compose["id"],

+             ArtifactBuildCompose.compose_id == Compose.id)

+ 

+         for build in builds_with_compose:

+             build.transition(

+                 ArtifactBuildState.FAILED.value,

+                 "ODCS compose %r is in failed state." % event.compose["id"])

file modified
+1

@@ -571,6 +571,7 @@ 

              "build_id": self.build_id,

              "url": build_url,

              "build_args": build_args,

+             "odcs_composes": [rel.compose.odcs_compose_id for rel in self.composes],

          }

  

      def get_root_dep_on(self):

@@ -0,0 +1,96 @@ 

+ # -*- coding: utf-8 -*-

+ # Copyright (c) 2019  Red Hat, Inc.

+ #

+ # Permission is hereby granted, free of charge, to any person obtaining a copy

+ # of this software and associated documentation files (the "Software"), to deal

+ # in the Software without restriction, including without limitation the rights

+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+ # copies of the Software, and to permit persons to whom the Software is

+ # furnished to do so, subject to the following conditions:

+ #

+ # The above copyright notice and this permission notice shall be included in

+ # all copies or substantial portions of the Software.

+ #

+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

+ # SOFTWARE.

+ #

+ # Written by Jan Kaluza <jkaluza@redhat.com>

+ 

+ from freshmaker import db

+ from freshmaker.models import (

+     Event, EventState, EVENT_TYPES,

+     ArtifactBuild, ArtifactType, ArtifactBuildState, ArtifactBuildCompose,

+     Compose

+ )

+ from freshmaker.events import ErrataAdvisoryRPMsSignedEvent

+ from freshmaker.handlers.internal import UpdateDBOnODCSComposeFail

+ from freshmaker.events import ODCSComposeStateChangeEvent

+ from tests import helpers

+ from odcs.common.types import COMPOSE_STATES

+ 

+ 

+ class TestUpdateDBOnODCSComposeFail(helpers.ModelsTestCase):

+ 

+     def setUp(self):

+         super(TestUpdateDBOnODCSComposeFail, self).setUp()

+         self.db_event = self._create_test_event(

+             "msg-1", "search-key-1", "build-1", 1)

+         # Create another DB event, build and compose just to have more data

+         # in database.

+         self.db_event_2 = self._create_test_event(

+             "msg-2", "search-key-2", "another-build-1", 2)

+ 

+     def _create_test_event(self, event_id, search_key, build_name, compose_id):

+         db_event = Event.create(

+             db.session, event_id, search_key,

+             EVENT_TYPES[ErrataAdvisoryRPMsSignedEvent],

+             state=EventState.INITIALIZED,

+             released=False)

+         build_1 = ArtifactBuild.create(

+             db.session, db_event, build_name, ArtifactType.IMAGE,

+             state=ArtifactBuildState.PLANNED)

+         compose_1 = Compose(odcs_compose_id=compose_id)

+         db.session.add(compose_1)

+         db.session.commit()

+         db.session.add(ArtifactBuildCompose(

+             build_id=build_1.id, compose_id=compose_1.id))

+         db.session.commit()

+         return db_event

+ 

+     def test_cannot_handle_if_compose_is_not_failed(self):

+         event = ODCSComposeStateChangeEvent(

+             'msg-id', {'id': 1, 'state': COMPOSE_STATES["done"]}

+         )

+         handler = UpdateDBOnODCSComposeFail()

+         can_handle = handler.can_handle(event)

+         self.assertFalse(can_handle)

+ 

+     def test_can_handle(self):

+         event = ODCSComposeStateChangeEvent(

+             'msg-id', {'id': 1, 'state': COMPOSE_STATES["failed"]}

+         )

+         handler = UpdateDBOnODCSComposeFail()

+         can_handle = handler.can_handle(event)

+         self.assertTrue(can_handle)

+ 

+     def test_handle_mark_build_as_failed(self):

+         event = ODCSComposeStateChangeEvent(

+             'msg-id', {'id': 1, 'state': COMPOSE_STATES["failed"]}

+         )

+         handler = UpdateDBOnODCSComposeFail()

+         handler.handle(event)

+ 

+         db.session.refresh(self.db_event)

+         build = self.db_event.builds[0]

+         self.assertEqual(build.state, ArtifactBuildState.FAILED.value)

+         self.assertEqual(build.state_reason,

+                          "ODCS compose 1 is in failed state.")

+ 

+         db.session.refresh(self.db_event_2)

+         build = self.db_event_2.builds[0]

+         self.assertEqual(build.state, ArtifactBuildState.PLANNED.value)

Also adds odcs_composes to ArtifactBuild JSON response to be able to search for all the composes used in a build easily.

Commit d805550 fixes this pull-request

Pull-Request has been merged by jkaluza

9 months ago

Pull-Request has been merged by jkaluza

9 months ago