From 738d2bd77a7419fd4e2831a71ba512d4ed8ad93a Mon Sep 17 00:00:00 2001
From: Zack Galbreath <zack.galbreath@kitware.com>
Date: Fri, 19 Oct 2018 15:14:15 -0400
Subject: Allow more customization for CDash reporter

Add new command line arguments to `spack install` that allow users
to set the build name, site name, and track in their CDash report.
---
 lib/spack/spack/cmd/install.py                 | 22 +++++++++++++++++++---
 lib/spack/spack/report.py                      | 10 ++++------
 lib/spack/spack/reporter.py                    |  5 ++---
 lib/spack/spack/reporters/cdash.py             | 19 +++++++++++--------
 lib/spack/spack/reporters/junit.py             |  4 ++--
 lib/spack/spack/test/cmd/install.py            | 23 +++++++++++++++++++++++
 share/spack/templates/reports/cdash/Site.xml   |  4 ++--
 share/spack/templates/reports/cdash/Update.xml |  4 ++--
 8 files changed, 65 insertions(+), 26 deletions(-)

diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py
index 628c2d3564..742c167aad 100644
--- a/lib/spack/spack/cmd/install.py
+++ b/lib/spack/spack/cmd/install.py
@@ -141,6 +141,24 @@ packages. If neither are chosen, don't run tests for any packages."""
         default=None,
         help="CDash URL where reports will be uploaded"
     )
+    subparser.add_argument(
+        '--cdash-build',
+        default=None,
+        help="""The name of the build that will be reported to CDash.
+Defaults to spec of the package to install."""
+    )
+    subparser.add_argument(
+        '--cdash-site',
+        default=None,
+        help="""The site name that will be reported to CDash.
+Defaults to current system hostname."""
+    )
+    subparser.add_argument(
+        '--cdash-track',
+        default='Experimental',
+        help="""Results will be reported to this group on CDash.
+Defaults to Experimental."""
+    )
     arguments.add_common_arguments(subparser, ['yes_to_all'])
 
 
@@ -224,9 +242,7 @@ def install(parser, args, **kwargs):
         tty.warn("Deprecated option: --run-tests: use --test=all instead")
 
     # 1. Abstract specs from cli
-    reporter = spack.report.collect_info(args.log_format,
-                                         ' '.join(args.package),
-                                         args.cdash_upload_url)
+    reporter = spack.report.collect_info(args.log_format, args)
     if args.log_file:
         reporter.filename = args.log_file
 
diff --git a/lib/spack/spack/report.py b/lib/spack/spack/report.py
index 74e5caf194..d092fe1c69 100644
--- a/lib/spack/spack/report.py
+++ b/lib/spack/spack/report.py
@@ -228,15 +228,14 @@ class collect_info(object):
 
     Args:
         format_name (str or None): one of the supported formats
-        install_command (str): the command line passed to spack
-        cdash_upload_url (str or None): where to upload the report
+        args (dict): args passed to spack install
 
     Raises:
         ValueError: when ``format_name`` is not in ``valid_formats``
     """
-    def __init__(self, format_name, install_command, cdash_upload_url):
+    def __init__(self, format_name, args):
         self.filename = None
-        if cdash_upload_url:
+        if args.cdash_upload_url:
             self.format_name = 'cdash'
             self.filename = 'cdash_report'
         else:
@@ -245,8 +244,7 @@ class collect_info(object):
         if self.format_name not in valid_formats:
             raise ValueError('invalid report type: {0}'
                              .format(self.format_name))
-        self.report_writer = report_writers[self.format_name](
-            install_command, cdash_upload_url)
+        self.report_writer = report_writers[self.format_name](args)
 
     def concretization_report(self, msg):
         self.report_writer.concretization_report(self.filename, msg)
diff --git a/lib/spack/spack/reporter.py b/lib/spack/spack/reporter.py
index 17efe23637..b2706db796 100644
--- a/lib/spack/spack/reporter.py
+++ b/lib/spack/spack/reporter.py
@@ -10,9 +10,8 @@ __all__ = ['Reporter']
 class Reporter(object):
     """Base class for report writers."""
 
-    def __init__(self, install_command, cdash_upload_url):
-        self.install_command = install_command
-        self.cdash_upload_url = cdash_upload_url
+    def __init__(self, args):
+        self.args = args
 
     def build_report(self, filename, report_data):
         pass
diff --git a/lib/spack/spack/reporters/cdash.py b/lib/spack/spack/reporters/cdash.py
index 7093afa2ef..068f9275b7 100644
--- a/lib/spack/spack/reporters/cdash.py
+++ b/lib/spack/spack/reporters/cdash.py
@@ -51,15 +51,17 @@ class CDash(Reporter):
     CDash instance hosted at https://mydomain.com/cdash.
     """
 
-    def __init__(self, install_command, cdash_upload_url):
-        Reporter.__init__(self, install_command, cdash_upload_url)
+    def __init__(self, args):
+        Reporter.__init__(self, args)
         self.template_dir = os.path.join('reports', 'cdash')
-        self.hostname = socket.gethostname()
+        self.cdash_upload_url = args.cdash_upload_url
+        self.install_command = ' '.join(args.package)
+        self.buildname = args.cdash_build or self.install_command
+        self.site = args.cdash_site or socket.gethostname()
         self.osname = platform.system()
         self.starttime = int(time.time())
-        # TODO: remove hardcoded use of Experimental here.
-        #       Make the submission model configurable.
-        self.buildstamp = time.strftime("%Y%m%d-%H%M-Experimental",
+        buildstamp_format = "%Y%m%d-%H%M-{0}".format(args.cdash_track)
+        self.buildstamp = time.strftime(buildstamp_format,
                                         time.localtime(self.starttime))
 
     def build_report(self, filename, report_data):
@@ -176,10 +178,11 @@ class CDash(Reporter):
     def initialize_report(self, filename, report_data):
         if not os.path.exists(filename):
             os.mkdir(filename)
-        report_data['install_command'] = self.install_command
+        report_data['buildname'] = self.buildname
         report_data['buildstamp'] = self.buildstamp
-        report_data['hostname'] = self.hostname
+        report_data['install_command'] = self.install_command
         report_data['osname'] = self.osname
+        report_data['site'] = self.site
 
     def upload(self, filename):
         if not self.cdash_upload_url:
diff --git a/lib/spack/spack/reporters/junit.py b/lib/spack/spack/reporters/junit.py
index 264da413f0..37f389f651 100644
--- a/lib/spack/spack/reporters/junit.py
+++ b/lib/spack/spack/reporters/junit.py
@@ -17,8 +17,8 @@ __all__ = ['JUnit']
 class JUnit(Reporter):
     """Generate reports of spec installations for JUnit."""
 
-    def __init__(self, install_command, cdash_upload_url):
-        Reporter.__init__(self, install_command, cdash_upload_url)
+    def __init__(self, args):
+        Reporter.__init__(self, args)
         self.template_file = os.path.join('reports', 'junit.xml')
 
     def build_report(self, filename, report_data):
diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py
index 904472f243..666d93020f 100644
--- a/lib/spack/spack/test/cmd/install.py
+++ b/lib/spack/spack/test/cmd/install.py
@@ -432,6 +432,29 @@ def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery,
             assert '<Text>' not in content
 
 
+@pytest.mark.disable_clean_stage_check
+def test_cdash_upload_extra_params(tmpdir, mock_fetch, install_mockery, capfd):
+    # capfd interferes with Spack's capturing
+    with capfd.disabled():
+        with tmpdir.as_cwd():
+            with pytest.raises((HTTPError, URLError)):
+                install(
+                    '--log-file=cdash_reports',
+                    '--cdash-build=my_custom_build',
+                    '--cdash-site=my_custom_site',
+                    '--cdash-track=my_custom_track',
+                    '--cdash-upload-url=http://localhost/fakeurl/submit.php?project=Spack',
+                    'a')
+            report_dir = tmpdir.join('cdash_reports')
+            assert report_dir in tmpdir.listdir()
+            report_file = report_dir.join('Build.xml')
+            assert report_file in report_dir.listdir()
+            content = report_file.open().read()
+            assert 'Site BuildName="my_custom_build"' in content
+            assert 'Name="my_custom_site"' in content
+            assert '-my_custom_track' in content
+
+
 @pytest.mark.disable_clean_stage_check
 def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd):
     with capfd.disabled():
diff --git a/share/spack/templates/reports/cdash/Site.xml b/share/spack/templates/reports/cdash/Site.xml
index a47ffd34e6..f0a150b6e5 100644
--- a/share/spack/templates/reports/cdash/Site.xml
+++ b/share/spack/templates/reports/cdash/Site.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Site BuildName="{{ install_command }}"
+<Site BuildName="{{ buildname }}"
       BuildStamp="{{ buildstamp }}"
-      Name="{{ hostname }}"
+      Name="{{ site }}"
       OSName="{{ osname }}"
 >
 
diff --git a/share/spack/templates/reports/cdash/Update.xml b/share/spack/templates/reports/cdash/Update.xml
index 39f3d6a337..2ef5de347d 100644
--- a/share/spack/templates/reports/cdash/Update.xml
+++ b/share/spack/templates/reports/cdash/Update.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Update>
-  <Site>{{ hostname }}</Site>
-  <BuildName>{{ install_command }}</BuildName>
+  <Site>{{ site }}</Site>
+  <BuildName>{{ buildname }}</BuildName>
   <BuildStamp>{{ buildstamp }}</BuildStamp>
   <StartTime>{{ starttime }}</StartTime>
   <EndTime>{{ endtime }}</EndTime>
-- 
cgit v1.2.3-70-g09d2