Perf dashboard should support authentication via a slave password
[WebKit-https.git] / Websites / perf.webkit.org / public / include / report-processor.php
index 233cda28f0725092a8780580479e02b57b79495c..54fad0ed83153af48062466b10f99f6b7f49990e 100644 (file)
@@ -39,16 +39,42 @@ class ReportProcessor {
         array_key_exists('buildTime', $report) or $this->exit_with_error('MissingBuildTime');
 
         $builder_info = array('name' => $report['builderName']);
-        if (!$existing_report_id)
-            $builder_info['password_hash'] = hash('sha256', $report['builderPassword']);
+        $slave_name = array_get($report, 'slaveName', NULL);
+        $slave_id = NULL;
+        if (!$existing_report_id) {
+            $hash = NULL;
+            if ($slave_name && array_key_exists('slavePassword', $report)) {
+                $hash = hash('sha256', $report['slavePassword']);
+                $slave = $this->db->select_first_row('build_slaves', 'slave', array('name' => $slave_name, 'password_hash' => $hash));
+                if ($slave)
+                    $slave_id = $slave['slave_id'];
+            } else if (array_key_exists('builderPassword', $report))
+                $hash = hash('sha256', $report['builderPassword']);
+
+            if (!$hash)
+                $this->exit_with_error('BuilderNotFound');
+            if (!$slave_id)
+                $builder_info['password_hash'] = $hash;
+        }
+
         if (array_key_exists('builderPassword', $report))
             unset($report['builderPassword']);
+        if (array_key_exists('slavePassword', $report))
+            unset($report['slavePassword']);
+
+        $builder_id = NULL;
+        if ($slave_id)
+            $builder_id = $this->db->select_or_insert_row('builders', 'builder', $builder_info);
+        else {
+            $builder = $this->db->select_first_row('builders', 'builder', $builder_info);
+            if (!$builder)
+                $this->exit_with_error('BuilderNotFound', array('name' => $builder_info['name']));
+            $builder_id = $builder['builder_id'];
+            if ($slave_name)
+                $slave_id = $this->db->select_or_insert_row('build_slaves', 'slave', array('name' => $slave_name));
+        }
 
-        $matched_builder = $this->db->select_first_row('builders', 'builder', $builder_info);
-        if (!$matched_builder)
-            $this->exit_with_error('BuilderNotFound', array('name' => $builder_info['name']));
-
-        $build_data = $this->construct_build_data($report, $matched_builder);
+        $build_data = $this->construct_build_data($report, $builder_id, $slave_id);
         if (!$existing_report_id)
             $this->store_report($report, $build_data);
 
@@ -67,16 +93,19 @@ class ReportProcessor {
         $this->runs->commit($platform_id, $build_id);
     }
 
-    private function construct_build_data($report, $builder) {
+    private function construct_build_data($report, $builder_id, $slave_id) {
         array_key_exists('buildNumber', $report) or $this->exit_with_error('MissingBuildNumber');
         array_key_exists('buildTime', $report) or $this->exit_with_error('MissingBuildTime');
 
-        return array('builder' => $builder['builder_id'], 'number' => $report['buildNumber'], 'time' => $report['buildTime']);
+        return array('builder' => $builder_id, 'slave' => $slave_id, 'number' => $report['buildNumber'], 'time' => $report['buildTime']);
     }
 
     private function store_report($report, $build_data) {
         assert(!$this->report_id);
-        $this->report_id = $this->db->insert_row('reports', 'report', array('builder' => $build_data['builder'], 'build_number' => $build_data['number'],
+        $this->report_id = $this->db->insert_row('reports', 'report', array(
+            'builder' => $build_data['builder'],
+            'slave' => $build_data['slave'],
+            'build_number' => $build_data['number'],
             'content' => json_encode($report)));
         if (!$this->report_id)
             $this->exit_with_error('FailedToStoreRunReport');
@@ -84,11 +113,15 @@ class ReportProcessor {
 
     private function resolve_build_id($build_data, $revisions) {
         // FIXME: This code has a race condition. See <rdar://problem/15876303>.
-        $results = $this->db->query_and_fetch_all("SELECT build_id FROM builds WHERE build_builder = $1 AND build_number = $2 AND build_time <= $3 AND build_time + interval '1 day' > $3",
+        $results = $this->db->query_and_fetch_all("SELECT build_id, build_slave FROM builds
+            WHERE build_builder = $1 AND build_number = $2 AND build_time <= $3 AND build_time + interval '1 day' > $3",
             array($build_data['builder'], $build_data['number'], $build_data['time']));
-        if ($results)
-            $build_id = $results[0]['build_id'];
-        else
+        if ($results) {
+            $first_result = $results[0];
+            if ($first_result['build_slave'] != $build_data['slave'])
+                $this->exit_with_error('MismatchingBuildSlave', array('storedBuild' => $results, 'reportedBuildData' => $build_data));
+            $build_id = $first_result['build_id'];
+        } else
             $build_id = $this->db->insert_row('builds', 'build', $build_data);
         if (!$build_id)
             $this->exit_with_error('FailedToInsertBuild', $build_data);