Perf dashboard tools shouldn't require server credentials in multiple configuration...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Oct 2015 23:05:43 +0000 (23:05 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Oct 2015 23:05:43 +0000 (23:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149994

Reviewed by Chris Dumez.

Made detect-changes.js and pull-svn.py pull username and passwords from the server config JSON to reduce
the number of JSON files that need to include credentials.

Also made each script reload the server config after sleep to allow dynamic credential updates.

In addition, change the server config JSON's format to include scheme, host, and port numbers separately
instead of a url since detect-changes.js needs each value separately.

This reduces the number of JSONs with credentials to two for our internal dashboard.

* tools/detect-changes.js:
(main): Added a property argument parsing. Now takes --server-config-json, --change-detection-config-json,
and --seconds-to-sleep like other scripts.
(parseArgument): Added.
(fetchManifestAndAnalyzeData): Reload the server config JSON.
(loadServerConfig): Added. Set settings.perfserver and settings.slave from the server config JSON. Also
add settings.perfserver.host to match the old format.
(configurationsForTesting): Fixed a bug that we throw an exception when a dashboard contains an empty cell.

* tools/pull-os-versions.py:
(main): Use load_server_config after each sleep.

* tools/pull-svn.py:
(main): Use load_server_config after each sleep.
(fetch_commits_and_submit): Use the perf dashboard's auth as subversion credential when useServerAuth is set.

* tools/sync-with-buildbot.py:
(main): Use load_server_config after each sleep.

* tools/util.py:
(load_server_config): Extracted from python scripts. Computes server's url from scheme, host, and port number
to match the old format python scripts except.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190900 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Websites/perf.webkit.org/ChangeLog
Websites/perf.webkit.org/tools/detect-changes.js
Websites/perf.webkit.org/tools/pull-os-versions.py
Websites/perf.webkit.org/tools/pull-svn.py
Websites/perf.webkit.org/tools/sync-with-buildbot.py
Websites/perf.webkit.org/tools/util.py

index 4a97830..42c7fd4 100644 (file)
@@ -1,3 +1,43 @@
+2015-10-12  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Perf dashboard tools shouldn't require server credentials in multiple configuration files
+        https://bugs.webkit.org/show_bug.cgi?id=149994
+
+        Reviewed by Chris Dumez.
+
+        Made detect-changes.js and pull-svn.py pull username and passwords from the server config JSON to reduce
+        the number of JSON files that need to include credentials.
+
+        Also made each script reload the server config after sleep to allow dynamic credential updates.
+
+        In addition, change the server config JSON's format to include scheme, host, and port numbers separately
+        instead of a url since detect-changes.js needs each value separately.
+
+        This reduces the number of JSONs with credentials to two for our internal dashboard.
+
+        * tools/detect-changes.js:
+        (main): Added a property argument parsing. Now takes --server-config-json, --change-detection-config-json,
+        and --seconds-to-sleep like other scripts.
+        (parseArgument): Added.
+        (fetchManifestAndAnalyzeData): Reload the server config JSON.
+        (loadServerConfig): Added. Set settings.perfserver and settings.slave from the server config JSON. Also
+        add settings.perfserver.host to match the old format.
+        (configurationsForTesting): Fixed a bug that we throw an exception when a dashboard contains an empty cell.
+
+        * tools/pull-os-versions.py:
+        (main): Use load_server_config after each sleep.
+
+        * tools/pull-svn.py:
+        (main): Use load_server_config after each sleep.
+        (fetch_commits_and_submit): Use the perf dashboard's auth as subversion credential when useServerAuth is set.
+
+        * tools/sync-with-buildbot.py:
+        (main): Use load_server_config after each sleep.
+
+        * tools/util.py:
+        (load_server_config): Extracted from python scripts. Computes server's url from scheme, host, and port number
+        to match the old format python scripts except.
+
 2015-10-11  Ryosuke Niwa  <rniwa@webkit.org>
 
         Build fix after r190817.  Now that pull-os-versions store fake timestamps, we need to bypass timestamp
index 84fa7e6..d5cde30 100644 (file)
@@ -7,32 +7,84 @@ var data = require('../public/v2/data.js');
 var RunsData = data.RunsData;
 var Statistics = require('../public/v2/js/statistics.js');
 
+// FIXME: We shouldn't use a global variable like this.
 var settings;
 function main(argv)
 {
-    if (argv.length < 3) {
-        console.error('Please specify the settings JSON path');
-        return 1;
-    }
+    var options = parseArgument(argv, [
+        {name: '--server-config-json', required: true},
+        {name: '--change-detection-config-json', required: true},
+        {name: '--seconds-to-sleep', type: parseFloat, default: 1200},
+    ]);
+    if (!options)
+        return;
 
-    settings = JSON.parse(fs.readFileSync(argv[2], 'utf8'));
+    settings = JSON.parse(fs.readFileSync(options['--change-detection-config-json'], 'utf8'));
+    settings.secondsToSleep = options['--seconds-to-sleep'];
 
-    fetchManifestAndAnalyzeData();
+    fetchManifestAndAnalyzeData(options['--server-config-json']);
 }
 
-function fetchManifestAndAnalyzeData()
+function parseArgument(argv, acceptedOptions) {
+    var args = argv.slice(2);
+    var options = {}
+    for (var i = 0; i < args.length; i += 2) {
+        var current = args[i];
+        var next = args[i + 1];
+        for (var option of acceptedOptions) {
+            if (current == option['name']) {
+                options[option['name']] = next;
+                next = null;
+                break;
+            }
+        }
+        if (next) {
+            console.error('Invalid argument:', current);
+            return null;
+        }
+    }
+    for (var option of acceptedOptions) {
+        var name = option['name'];
+        if (option['required'] && !(name in options)) {
+            console.log('Required argument', name, 'is missing');
+            return null;
+        }
+        var value = options[name] || option['default'];
+        var converter = option['type'];
+        options[name] = converter ? converter(value) : value;
+    }
+    return options;
+}
+
+function fetchManifestAndAnalyzeData(serverConfigJSON)
 {
+    loadServerConfig(serverConfigJSON);
+
     getJSON(settings.perfserver, '/data/manifest.json').then(function (manifest) {
         return mapInOrder(configurationsForTesting(manifest), analyzeConfiguration);
     }).catch(function (reason) {
-        console.error('Failed to obtain the manifest file');
+        console.error('Failed to obtain the manifest file', reason);
     }).then(function () {
         console.log('');
         console.log('Sleeing for', settings.secondsToSleep, 'seconds');
-        setTimeout(fetchManifestAndAnalyzeData, settings.secondsToSleep * 1000);
+        setTimeout(function () {
+            fetchManifestAndAnalyzeData(serverConfigJSON);
+        }, settings.secondsToSleep * 1000);
     });
 }
 
+function loadServerConfig(serverConfigJSON)
+{
+    var serverConfig = JSON.parse(fs.readFileSync(serverConfigJSON, 'utf8'));
+
+    var server = serverConfig['server'];
+    if ('auth' in server)
+        server['auth'] = server['auth']['username'] + ':' + server['auth']['password'];
+
+    settings.perfserver = server;
+    settings.slave = serverConfig['slave'];
+}
+
 function mapInOrder(array, callback, startIndex)
 {
     if (startIndex === undefined)
@@ -54,8 +106,12 @@ function configurationsForTesting(manifest)
         var dashboard = manifest.dashboards[name];
         for (var row of dashboard) {
             for (var cell of row) {
-                if (cell instanceof Array)
-                    configurations.push({platformId: parseInt(cell[0]), metricId: parseInt(cell[1])});
+                if (cell instanceof Array) {
+                    var platformId = parseInt(cell[0]);
+                    var metricId = parseInt(cell[1]);
+                    if (!isNaN(platformId) && !isNaN(metricId))
+                        configurations.push({platformId: platformId, metricId: metricId});
+                }
             }
         }
     }
index 7617a1b..be28caf 100755 (executable)
@@ -14,7 +14,7 @@ from datetime import datetime
 from xml.dom.minidom import parseString as parseXmlString
 from util import submit_commits
 from util import text_content
-from util import setup_auth
+from util import load_server_config
 
 
 def main(argv):
@@ -27,13 +27,10 @@ def main(argv):
     with open(args.os_config_json) as os_config_json:
         os_config_list = json.load(os_config_json)
 
-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
     fetchers = [OSBuildFetcher(os_config) for os_config in os_config_list]
 
     while True:
+        server_config = load_server_config(args.server_config_json)
         for fetcher in fetchers:
             fetcher.fetch_and_report_new_builds(server_config)
         print "Sleeping for %d seconds" % args.seconds_to_sleep
index d32228d..c0c64a4 100755 (executable)
@@ -9,7 +9,7 @@ import time
 import urllib2
 
 from xml.dom.minidom import parseString as parseXmlString
-from util import setup_auth
+from util import load_server_config
 from util import submit_commits
 from util import text_content
 
@@ -22,14 +22,11 @@ def main(argv):
     parser.add_argument('--max-fetch-count', type=int, default=10, help='The number of commits to fetch at once')
     args = parser.parse_args()
 
-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
     with open(args.svn_config_json) as svn_config_json:
         svn_config = json.load(svn_config_json)
 
     while True:
+        server_config = load_server_config(args.server_config_json)
         for repository_info in svn_config:
             fetch_commits_and_submit(repository_info, server_config, args.max_fetch_count)
         print "Sleeping for %d seconds..." % args.seconds_to_sleep
@@ -44,6 +41,10 @@ def fetch_commits_and_submit(repository, server_config, max_fetch_count):
         print "Determining the stating revision for %s" % repository['name']
         repository['revisionToFecth'] = determine_first_revision_to_fetch(server_config['server']['url'], repository['name'])
 
+    if 'useServerAuth' in repository:
+        repository['username'] = server_config['server']['auth']['username']
+        repository['password'] = server_config['server']['auth']['password']
+
     pending_commits = []
     for unused in range(max_fetch_count):
         commit = fetch_commit_and_resolve_author(repository, repository.get('accountNameFinderScript', None), repository['revisionToFecth'])
index e410575..084c84b 100755 (executable)
@@ -9,7 +9,7 @@ import time
 import urllib
 import urllib2
 
-from util import setup_auth
+from util import load_server_config
 
 
 def main():
@@ -27,14 +27,9 @@ def main():
 
     configurations = load_config(args.builder_config_json, args.buildbot_url.strip('/'))
 
-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
-    build_requests_url = server_config['server']['url'] + '/api/build-requests/' + args.triggerable
-
     request_updates = {}
     while True:
+        server_config = load_server_config(args.server_config_json)
         request_updates.update(find_request_updates(configurations, args.lookback_count))
         if request_updates:
             print 'Updating the build requests %s...' % ', '.join(map(str, request_updates.keys()))
@@ -45,6 +40,8 @@ def main():
             'buildRequestUpdates': request_updates,
             'slaveName': server_config['slave']['name'],
             'slavePassword': server_config['slave']['password']}
+
+        build_requests_url = server_config['server']['url'] + '/api/build-requests/' + args.triggerable
         response = update_and_fetch_build_requests(build_requests_url, payload)
         open_requests = response.get('buildRequests', [])
 
index 86956b4..f31f02e 100644 (file)
@@ -51,3 +51,12 @@ def setup_auth(server):
     password_manager.add_password(realm=auth['realm'], uri=server['url'], user=auth['username'], passwd=auth['password'])
     auth_handler = HTTP_AUTH_HANDLERS[auth['type']](password_manager)
     urllib2.install_opener(urllib2.build_opener(auth_handler))
+
+
+def load_server_config(json_path):
+    with open(json_path) as server_config_json:
+        server_config = json.load(server_config_json)
+        server = server_config['server']
+        server['url'] = server['scheme'] + '://' + server['host'] + ':' + str(server['port'])
+        setup_auth(server)
+        return server_config