From 2bd4662cc09b4aba999a550bdaf731ed894c286b Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Sep 16 2019 14:12:59 +0000 Subject: Send a message when a CoreOS operation is done Signed-off-by: Aurélien Bompard --- diff --git a/robosignatory/cli.py b/robosignatory/cli.py index 857781a..0c50922 100644 --- a/robosignatory/cli.py +++ b/robosignatory/cli.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals, absolute_import + import os import click @@ -5,7 +7,9 @@ from fedora_messaging.config import conf import robosignatory.work from robosignatory.tag import TagSigner -from robosignatory.coreos import CoreOSSigner, ArtifactSignerWrapper, OSTreeSignerWrapper +from robosignatory.coreos import ( + CoreOSSigner, ArtifactSignerWrapper, OSTreeSignerWrapper, SigningFailed +) from robosignatory import utils @@ -55,7 +59,10 @@ def coreos_artifact(file_url, checksum): consumer = CoreOSSigner(conf["consumer_config"]) key = consumer.get_key(None) signing_wrapper = ArtifactSignerWrapper(consumer.signer, key, consumer.bucket) - signing_wrapper.sign(file_url, checksum) + try: + signing_wrapper.sign(file_url, checksum) + except SigningFailed as e: + click.fail(str(e)) @cli.command("sign-coreos-ostree") @@ -65,4 +72,7 @@ def coreos_ostree(file_url, checksum): consumer = CoreOSSigner(conf["consumer_config"]) key = consumer.get_key(None) signing_wrapper = OSTreeSignerWrapper(consumer.signer, key, consumer.bucket) - signing_wrapper.sign(file_url, checksum) + try: + signing_wrapper.sign(file_url, checksum) + except SigningFailed as e: + click.fail(str(e)) diff --git a/robosignatory/coreos.py b/robosignatory/coreos.py index 20c0438..693361f 100644 --- a/robosignatory/coreos.py +++ b/robosignatory/coreos.py @@ -9,6 +9,7 @@ import tempfile import boto3 import robosignatory.utils as utils from six.moves.urllib.parse import urlparse +from fedora_messaging.api import Message, publish log = logging.getLogger(__name__) @@ -48,14 +49,35 @@ class CoreOSSigner(object): ) key = self.get_key(msg) - if msg.topic.endswith('.coreos.build.request.artifacts-sign'): - wrapper = ArtifactSignerWrapper(self.signer, key, self.bucket) - for artifact in msg.body["artifacts"]: - wrapper.sign(artifact["file"], artifact["checksum"]) + response = Message( + topic="{}.finished".format(msg.topic), + body={ + "build_id": msg.body["build_id"], + "stream": msg.body["stream"], + "basearch": msg.body["basearch"], + } + ) + + try: + if msg.topic.endswith('.coreos.build.request.artifacts-sign'): + wrapper = ArtifactSignerWrapper(self.signer, key, self.bucket) + for artifact in msg.body["artifacts"]: + wrapper.sign(artifact["file"], artifact["checksum"]) + + elif msg.topic.endswith('.coreos.build.request.ostree-sign'): + wrapper = OSTreeSignerWrapper(self.signer, key, self.bucket) + wrapper.sign(msg.body["commit_object"], msg.body["checksum"]) + except SigningFailed as e: + log.error(e) + response.body["status"] = "FAILURE" + publish(response) + else: + response.body["status"] = "SUCCESS" + publish(response) - elif msg.topic.endswith('.coreos.build.request.ostree-sign'): - wrapper = OSTreeSignerWrapper(self.signer, key, self.bucket) - wrapper.sign(msg.body["commit_object"], msg.body["checksum"]) + +class SigningFailed(Exception): + pass class SignerWrapper(object): @@ -90,8 +112,7 @@ class SignerWrapper(object): log.info("Checking hash for %s", filepath) if utils.get_hash(local_filepath) != checksum: - log.error("Incorrect SHA256 for %s, not signing", filepath) - return + raise SigningFailed("Incorrect SHA256 for {}, not signing".format(filepath)) log.info("Signing %s", filepath) sig_filepath = self._get_sig_filepath(local_filepath) @@ -99,12 +120,14 @@ class SignerWrapper(object): log.info('Signing command line: %s', cmdline) ret, stdout, stderr = utils.run_command(cmdline) if ret != 0: - log.error('Error signing! Signing output: %s, stdout: %s, ' - 'stderr: %s', ret, stdout, stderr) - return + raise SigningFailed( + 'Error signing! Signing output: {}, stdout: {}, stderr: {}'.format( + ret, stdout, stderr) + ) if not os.path.exists(sig_filepath): - log.error("Signer did not produce any signature file for %s", filepath) - return + raise SigningFailed( + "Signer did not produce any signature file for {}".format(filepath) + ) log.debug('Fixing signature file permissions') # Sigul writes it as 0600, which makes a lot of sense as a general file # mode for it, but this is just a signature file that we want published diff --git a/tests/test_coreos.py b/tests/test_coreos.py index de9375a..c3ae9c3 100644 --- a/tests/test_coreos.py +++ b/tests/test_coreos.py @@ -3,8 +3,9 @@ import unittest import copy from collections import namedtuple -from fedora_messaging.api import Message import mock +from fedora_messaging.api import Message +from fedora_messaging.testing import mock_sends from robosignatory.coreos import CoreOSSigner @@ -72,13 +73,26 @@ class TestCoreOS(unittest.TestCase): self.consumer = CoreOSSigner(TEST_CONFIG) self.consumer.bucket = mock.Mock() + def _get_response_message(self, source_msg, failed=False): + return Message( + topic=source_msg.topic + ".finished", + body={ + "build_id": source_msg.body["build_id"], + "stream": source_msg.body["stream"], + "basearch": source_msg.body["basearch"], + "status": "FAILURE" if failed else "SUCCESS", + } + ) + @mock.patch('robosignatory.coreos.utils.run_command') def test_artifacts_sign(self, run_command): self.consumer.bucket.download_file.side_effect = fake_download_and_artifact_sign run_command.return_value = 0, "", "" self.consumer.bucket.objects.filter.return_value = [S3Object(size=0)] + expected_response = self._get_response_message(ARTIFACTS_MESSAGE) - self.consumer.consume(ARTIFACTS_MESSAGE) + with mock_sends(expected_response): + self.consumer.consume(ARTIFACTS_MESSAGE) self.consumer.bucket.download_file.assert_called() assert self.consumer.bucket.download_file.call_args_list[0][0][0] == "some/path/test1" @@ -91,8 +105,10 @@ class TestCoreOS(unittest.TestCase): self.consumer.bucket.download_file.side_effect = fake_download_and_ostree_sign run_command.return_value = 0, "", "" self.consumer.bucket.objects.filter.return_value = [S3Object(size=0)] + expected_response = self._get_response_message(OSTREE_MESSAGE) - self.consumer.consume(OSTREE_MESSAGE) + with mock_sends(expected_response): + self.consumer.consume(OSTREE_MESSAGE) self.consumer.bucket.download_file.assert_called() assert self.consumer.bucket.download_file.call_args_list[0][0][0] == "some/path/test1" @@ -106,8 +122,10 @@ class TestCoreOS(unittest.TestCase): new_body["artifacts"][0]["checksum"] = "wrong-checksum" msg = Message(topic=ARTIFACTS_MESSAGE.topic, body=new_body) self.consumer.bucket.download_file.side_effect = fake_download + expected_response = self._get_response_message(ARTIFACTS_MESSAGE, failed=True) - self.consumer.consume(msg) + with mock_sends(expected_response): + self.consumer.consume(msg) self.consumer.bucket.download_file.assert_called() run_command.assert_not_called() @@ -117,8 +135,10 @@ class TestCoreOS(unittest.TestCase): def test_signing_failed(self, run_command): self.consumer.bucket.download_file.side_effect = fake_download run_command.return_value = 1, "stdout", "stderr" + expected_response = self._get_response_message(ARTIFACTS_MESSAGE, failed=True) - self.consumer.consume(ARTIFACTS_MESSAGE) + with mock_sends(expected_response): + self.consumer.consume(ARTIFACTS_MESSAGE) self.consumer.bucket.download_file.assert_called() run_command.assert_called() @@ -128,8 +148,10 @@ class TestCoreOS(unittest.TestCase): def test_no_signature(self, run_command): self.consumer.bucket.download_file.side_effect = fake_download run_command.return_value = 0, "stdout", "stderr" + expected_response = self._get_response_message(ARTIFACTS_MESSAGE, failed=True) - self.consumer.consume(ARTIFACTS_MESSAGE) + with mock_sends(expected_response): + self.consumer.consume(ARTIFACTS_MESSAGE) self.consumer.bucket.download_file.assert_called() run_command.assert_called()