From 551d28b7ed7a098cf14a7e8a023c4606726ade31 Mon Sep 17 00:00:00 2001
From: Jan Kaluza <jkaluza@redhat.com>
Date: May 12 2017 08:23:33 +0000
Subject: Add robosignatory-signmodule cli command


Signed-off-by: Jan Kaluza <jkaluza@redhat.com>

---

diff --git a/robosignatory/cli.py b/robosignatory/cli.py
index d9e6241..1cecdac 100644
--- a/robosignatory/cli.py
+++ b/robosignatory/cli.py
@@ -79,3 +79,14 @@ def atomicsigner():
     val = config['robosignatory.ostree_refs'][ref]
 
     robosignatory.work.process_atomic(signer, ref, commitid, **val)
+
+def modulesigner():
+    if len(sys.argv) != 3:
+        print 'Usage: %s <koji-instance> <module-tag>' % sys.argv[0]
+        sys.exit(1)
+
+    koji_instance = sys.argv[1]
+    tag = sys.argv[2]
+
+    signer = TagSignerConsumer(None)
+    signer.sign_modular_tag(koji_instance, tag)
diff --git a/robosignatory/tagconsumer.py b/robosignatory/tagconsumer.py
index a77b02c..65e609e 100644
--- a/robosignatory/tagconsumer.py
+++ b/robosignatory/tagconsumer.py
@@ -304,8 +304,9 @@ class TagSignerConsumer(fedmsg.consumers.FedmsgConsumer):
 
             tag_info = instance['tags'][tag]
 
-        log.info('Going to sign with %s (%s) and move to %s',
-                 tag_info['key'], tag_info['keyid'], tag_info['to'])
+        log.info('Going to sign %s with %s (%s) and move to %s',
+                 build_nvr, tag_info['key'], tag_info['keyid'],
+                 tag_info['to'])
 
         rpms = utils.get_rpms(instance['client'],
                               build_nvr=build_nvr,
@@ -354,3 +355,35 @@ class TagSignerConsumer(fedmsg.consumers.FedmsgConsumer):
             else:
                 instance['client'].tagBuild(tag_info['to'], build_id, False,
                                             tag)
+
+    def sign_modular_tag(self, koji_instance, tag):
+        """
+        Signs all the latest RPMs in a modular tag
+        """
+        if koji_instance not in self.koji_clients:
+            log.error('Koji instance not known.')
+            return
+
+        # Get the list of all builds in the tag.
+        instance = self.koji_clients[koji_instance]
+        builds = utils.get_builds_in_tag(instance["client"], tag)
+        if not builds:
+            log.info("No build to sign in given tag.")
+            return
+
+        # Try signing the first build. This queries the PDC to find out
+        # the base module for a build and therefore is slow. Therefore
+        # we do that only for the first build. In the end it adds the
+        # resulting signing key to instance["tags"] cache and that is what
+        # we use for the rest of builds in this module.
+        self.sign_modular_rpms(builds[0]["nvr"], builds[0]["build_id"], tag,
+                               koji_instance)
+        if tag not in instance["tags"] or not instance["tags"][tag]:
+            # No need to log anything, sign_module_rpms logs an error
+            # when it cannot sign a module build.
+            return
+
+        # Sign the rest of builds in tag.
+        for build in builds[1:]:
+            self.dowork(build["nvr"], build["build_id"], tag, koji_instance,
+                        skip_tagging=False)
diff --git a/robosignatory/utils.py b/robosignatory/utils.py
index e78616b..b86afa7 100644
--- a/robosignatory/utils.py
+++ b/robosignatory/utils.py
@@ -1,6 +1,7 @@
 import abc
 import pkg_resources
 import subprocess
+import koji
 
 import logging
 log = logging.getLogger('robosignatory.utils')
@@ -25,6 +26,18 @@ def get_rpms(koji_client, build_nvr=None, build_id=None, sigkey=None):
         rpminfo['%s.%s' % (rpm['nvr'], rpm['arch'])] = info
     return rpminfo
 
+def get_builds_in_tag(koji_client, tag):
+    """ Return the list of builds in Koji tag. """
+
+    try:
+        rpms, builds = koji_client.listTaggedRPMS(tag, latest=True)
+    except koji.GenericError as e:
+        log.exception("Failed to list rpms in tag %r" % tag)
+        # If the tag doesn't exist.. then there are no rpms in that tag.
+        return []
+
+    return builds
+
 
 def run_command(command):
     child = subprocess.Popen(command, stdin=subprocess.PIPE,
diff --git a/setup.py b/setup.py
index 80b6cc9..2999a28 100644
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,7 @@ setup(
     robosignatory-signbuild = robosignatory.cli:buildsigner
     robosignatory-signtagbuild = robosignatory.cli:tagsigner
     robosignatory-signatomic = robosignatory.cli:atomicsigner
+    robosignatory-signmodule = robosignatory.cli:modulesigner
 
     [robosignatory.signing.helpers]
     echo = robosignatory.utils:EchoHelper

