Perf dashboard should have the capability to test local UI with production data
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Oct 2015 21:04:03 +0000 (21:04 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Oct 2015 21:04:03 +0000 (21:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149834

Reviewed by Chris Dumez.

Added tools/run-with-remote-server.py which runs a local httpd server and pulls data from a remote server.

* Install.md: Added the instruction on how to use the script. Also updated the remaining instructions
for El Capitan.
* config.json: Added remote server configurations.
* public/admin/fetch-from-remote.php: Added. This script fetches JSON from the remote server specified in
config.json and caches the results in the location specified as "cacheDirectory" in config.json.
(main):
(fetch_remote):
* public/include/db.php:
(config_path): Extracted from generate_data_file.
(generate_data_file):
* tools/remote-server-relay.conf: Added. Apache 2.4 configuration file for a local http server launched by
run-with-remote-server.py.
* tools/run-with-remote-server.py: Added. Launches Apache with the right set of directives.
(main):
(abspath_from_root):

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

Websites/perf.webkit.org/ChangeLog
Websites/perf.webkit.org/Install.md
Websites/perf.webkit.org/config.json
Websites/perf.webkit.org/public/admin/fetch-from-remote.php [new file with mode: 0644]
Websites/perf.webkit.org/public/include/db.php
Websites/perf.webkit.org/tools/remote-server-relay.conf [new file with mode: 0644]
Websites/perf.webkit.org/tools/run-with-remote-server.py [new file with mode: 0755]

index cb38daa..86da492 100644 (file)
@@ -1,3 +1,28 @@
+2015-10-06  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Perf dashboard should have the capability to test local UI with production data
+        https://bugs.webkit.org/show_bug.cgi?id=149834
+
+        Reviewed by Chris Dumez.
+
+        Added tools/run-with-remote-server.py which runs a local httpd server and pulls data from a remote server.
+
+        * Install.md: Added the instruction on how to use the script. Also updated the remaining instructions
+        for El Capitan.
+        * config.json: Added remote server configurations.
+        * public/admin/fetch-from-remote.php: Added. This script fetches JSON from the remote server specified in
+        config.json and caches the results in the location specified as "cacheDirectory" in config.json.
+        (main):
+        (fetch_remote):
+        * public/include/db.php:
+        (config_path): Extracted from generate_data_file.
+        (generate_data_file):
+        * tools/remote-server-relay.conf: Added. Apache 2.4 configuration file for a local http server launched by
+        run-with-remote-server.py.
+        * tools/run-with-remote-server.py: Added. Launches Apache with the right set of directives.
+        (main):
+        (abspath_from_root):
+
 2015-07-13  Ryosuke Niwa  <rniwa@webkit.org>
 
         Fix a typo.
index 2f2a03c..325ce19 100644 (file)
@@ -1,7 +1,6 @@
 # Checking Out the Code and Installing Required Applications
 
-The instructions assume you're using Mac OS X (Mavericks for Server.app case and Mountain Lion without Server.app) as the
-host server, and assume that we're installing this application at `/Volumes/Data/perf.webkit.org`.
+The instructions assume you're using Mac OS X as the host server and installing this application at `/Volumes/Data/perf.webkit.org`.
 
 You can choose between using Server.app or install the required tools separately
 
@@ -9,7 +8,33 @@ You can choose between using Server.app or install the required tools separately
 2. Install node.
 3. Install Xcode with command line tools (only needed for svn)
 4. `svn co https://svn.webkit.org/repository/webkit/trunk/Websites/perf.webkit.org /Volumes/Data/perf.webkit.org`
-5. Inside `/Volumes/Data/perf.webkit.org`, run `npm install pg`.
+5. Inside `/Volumes/Data/perf.webkit.org`, run `npm install pg` and `mkdir -m 755 public/data/`
+
+# Testing Local UI Changes with Production Data
+
+The front end has the capability to pull data from a production server without replicating the database locally on OS X (Yosemite and later).
+To use this feature, modify `config.json`'s `remoteServer` entry so that "remoteServer.url" points to your production server,
+and "remoteServer.basicAuth" specifies the username and the password that is used by the production sever.
+
+Remove "basicAuth" entry for production servers that doesn't require a basic authentication (e.g. perf.webkit.org).
+
+```json
+{
+    "url": "http://perf.webkit.org",
+    "basicAuth": {
+        "username": "webkitten",
+        "password": "webkitten's secret password"            
+    }
+}
+```
+
+Then run `tools/run-with-remote-server.py`. This launches a httpd server on port 8080.
+
+The initial few page loads after starting the script could take as much as a few minutes depending on your production sever's configurations
+since Apache needs to start a pool of processes. Reloading the dashboards few times should bring the load time under control.
+
+The script caches remote server's responses under `public/data/remote-cache` and never revalidates them (to allow offline work).
+If you needed the latest content, delete caches stored in this directory by running `rm -rf public/data/remote-cache`.
 
 
 # Configuring Apache
@@ -20,29 +45,30 @@ You can use apachectl to start/stop/restart apache server from the command line:
  - Stopping httpd: `sudo apachectl stop`
  - Restarting httpd: `sudo apachectl restart`
 
+The apache logs are located at `/private/var/log/apache2`.
+
 ## Instructions if you're using Server.app
 
  - Enable PHP web applications
- - Go to Server Website / Store Site Files In, change it to /Volumes/Data/perf.webkit.org/public/`
+ - Go to Server Website / Store Site Files In, change it to `/Volumes/Data/perf.webkit.org/public/`
  - Go to Server Website / Edit advanced settings, enable Allow overrides using .htaccess files
+ - httpd config file is located at `/Library/Server/Web/Config/apache2/sites/0000_any_80.conf` (and/or 0000_any_`PORT#`.conf)
 
 ## Instructions if you're not using Server.app
 
  - Edit /private/etc/apache2/httpd.conf
 
      1. Change DocumentRoot to `/Volumes/Data/perf.webkit.org/public/`
-     2. Uncomment `"LoadModule php5_module libexec/apache2/libphp5.so"`
+     2. Uncomment `LoadModule php5_module libexec/apache2/libphp5.so`
+     3. Uncomment `LoadModule rewrite_module libexec/apache2/mod_rewrite.so`
+     4. Uncomment `LoadModule deflate_module libexec/apache2/mod_deflate.so`
 
  - In Mavericks and later, copy php.ini to load pdo_pgsql.so pgsql.so.
     `sudo cp /Applications/Server.app/Contents/ServerRoot/etc/php.ini /etc/`
+ - In El Capitan and later, comment out the `LockFile` directive in `/private/etc/apache2/extra/httpd-mpm.conf`
+   since the directive has been superseded by `Mutex` directive.
 
-
-## Common directives for the related apache config file
-
-  httpd config file is located at:
-
-    - With Server.app: /Library/Server/Web/Config/apache2/sites/0000_any_80.conf (and/or 0000_any_`PORT#`.conf)
-    - Without: /private/etc/apache2/httpd.conf
+## Production Configurations
 
  1. Update ServerAdmin to your email address
  2. Add the following directives to enable gzip:
@@ -56,13 +82,10 @@ You can use apachectl to start/stop/restart apache server from the command line:
         Options Indexes MultiViews
         php_flag zlib.output_compression on
 
-The apache logs are located at `/private/var/log/apache2`.
-
-
-# Protecting the Administrative Pages to Prevent Execution of Arbitrary Code
+### Protecting the Administrative Pages to Prevent Execution of Arbitrary Code
 
 By default, the application gives the administrative privilege to everyone. Anyone can add, remove, or edit tests,
-builders, and other entities in the database and may even execute arbitrary JavaScript on the server via aggregators.
+builders, and other entities in the database.
 
 We recommend protection via Digest Auth on https connection.
 
@@ -97,8 +120,9 @@ The binaries located in PostgreSQL's directory, or if you're using Server.app in
 Run `database/init-database.sql` in psql as `webkit-perf-db-user`:
 `/Applications/Server.app/Contents/ServerRoot/usr/bin/psql webkit-perf-db -h localhost --username webkit-perf-db-user -f init-database.sql`
 
-## Making a Backup of the Database
+## Making a Backup and Restoring
 
 Run `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump -h localhost --no-owner -f <filepath> webkit-perf-db | gzip > backup.gz`
 
-To restore, setup a new database and run `gunzip backup.gz | /Applications/Server.app/Contents/ServerRoot/usr/bin/psql webkit-perf-db -h localhost --username webkit-perf-db-user`
+To restore, setup a new database and run
+`gunzip backup.gz | /Applications/Server.app/Contents/ServerRoot/usr/bin/psql webkit-perf-db -h localhost --username webkit-perf-db-user`
index 8b1d79a..8991e55 100644 (file)
         "hostname": "localhost",
         "port": 80
     },
+    "cacheDirectory": "public/data/remote-cache/",
+    "remoteServer": {
+        "httpdConfig": "tools/remote-server-relay.conf",
+        "httpdPID": "tools/remote-server-relay.pid",
+        "httpdErroLog": "tools/remote-server-relay.log",
+        "url": "http://perf.webkit.org",
+        "basicAuth": {
+            "username": "username",
+            "password": "password"
+        }
+    },
     "defaultDashboard": [[]],
     "dashboards": {}
 }
diff --git a/Websites/perf.webkit.org/public/admin/fetch-from-remote.php b/Websites/perf.webkit.org/public/admin/fetch-from-remote.php
new file mode 100644 (file)
index 0000000..d6c4099
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+require('../include/db.php');
+
+function main($path)
+{
+    $remote_server = config('remoteServer');
+
+    $remote_url = $remote_server['url'] . $path;
+    $cache_path = config_path('cacheDirectory', hash("sha256", $remote_url));
+
+    $content = @file_get_contents($cache_path);
+    if ($content === FALSE) {
+        $content = fetch_remote($remote_server, $remote_url);
+        if ($content === FALSE) {
+            header('HTTP/1.0 404 Not Found');
+            echo 'NotFound';
+            exit(1);
+        }
+        file_put_contents($cache_path, $content);
+    }
+
+    header('Content-Type: application/json');
+    header('Content-Length: ' . strlen($content));
+    echo $content;
+}
+
+function fetch_remote($remote_server, $remote_url)
+{
+    $auth = array_get($remote_server, 'basicAuth');
+
+    $header = '';
+    if ($auth)
+        $header = 'Authorization: Basic ' . base64_encode($auth['username'] . ':' . $auth['password']);
+
+    $context = stream_context_create(array('http' => array('method' => 'GET', 'header' => $header)));
+
+    return @file_get_contents($remote_url, false, $context);
+}
+
+main(array_get($_SERVER, 'PATH_INFO', ''));
+
+?>
index 209f115..e5b4394 100644 (file)
@@ -36,10 +36,14 @@ function config($key) {
     return $_config[$key];
 }
 
+function config_path($key, $path) {
+    return CONFIG_DIR . config($key) . '/' . $path;
+}
+
 function generate_data_file($filename, $content) {
     if (!assert(ctype_alnum(str_replace(array('-', '_', '.'), '', $filename))))
         return FALSE;
-    return file_put_contents(CONFIG_DIR . config('dataDirectory') . '/' . $filename, $content);
+    return file_put_contents(config_path('dataDirectory'. $filename), $content);
 }
 
 if (config('debug')) {
diff --git a/Websites/perf.webkit.org/tools/remote-server-relay.conf b/Websites/perf.webkit.org/tools/remote-server-relay.conf
new file mode 100644 (file)
index 0000000..1e98c4a
--- /dev/null
@@ -0,0 +1,63 @@
+ServerRoot "/usr"
+Listen 8080
+
+LoadModule authn_core_module libexec/apache2/mod_authn_core.so
+LoadModule authz_core_module libexec/apache2/mod_authz_core.so
+LoadModule deflate_module libexec/apache2/mod_deflate.so
+LoadModule log_config_module libexec/apache2/mod_log_config.so
+LoadModule log_forensic_module libexec/apache2/mod_log_forensic.so
+LoadModule env_module libexec/apache2/mod_env.so
+LoadModule headers_module libexec/apache2/mod_headers.so
+LoadModule setenvif_module libexec/apache2/mod_setenvif.so
+LoadModule mime_module libexec/apache2/mod_mime.so
+LoadModule unixd_module libexec/apache2/mod_unixd.so
+LoadModule status_module libexec/apache2/mod_status.so
+LoadModule negotiation_module libexec/apache2/mod_negotiation.so
+LoadModule dir_module libexec/apache2/mod_dir.so
+LoadModule alias_module libexec/apache2/mod_alias.so
+LoadModule rewrite_module libexec/apache2/mod_rewrite.so
+LoadModule mime_module libexec/apache2/mod_mime.so
+LoadModule php5_module libexec/apache2/libphp5.so
+LoadModule negotiation_module libexec/apache2/mod_negotiation.so
+
+<Directory />
+    Options Indexes FollowSymLinks MultiViews
+    AllowOverride None
+    Require all granted
+</Directory>
+
+<IfModule dir_module>
+    DirectoryIndex index.html index.php
+</IfModule>
+
+LogLevel warn
+
+RewriteEngine On
+RewriteRule "/data/(.*)$" "/admin/fetch-from-remote.php/data/$1"
+RewriteRule "/api/(.*)$" "/admin/fetch-from-remote.php/api/$1"
+
+<IfModule log_config_module>
+    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+    LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+    <IfModule logio_module>
+      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+    </IfModule>
+
+    CustomLog |/usr/bin/tee common
+    ErrorLog |/usr/bin/tee
+</IfModule>
+
+<IfModule mime_module>
+    AddType text/html .html
+    AddType text/html .htm
+    AddType text/css .css
+    AddType text/javascript .js
+</IfModule>
+
+<IfModule php5_module>
+       AddType application/x-httpd-php .php
+       AddType application/x-httpd-php-source .phps
+</IfModule>
+
+Include /private/etc/apache2/extra/httpd-mpm.conf
diff --git a/Websites/perf.webkit.org/tools/run-with-remote-server.py b/Websites/perf.webkit.org/tools/run-with-remote-server.py
new file mode 100755 (executable)
index 0000000..5421d22
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import json
+import os
+import subprocess
+import tempfile
+
+
+def main():
+    with open(abspath_from_root('config.json')) as config_file:
+        config = json.load(config_file)
+        cache_dir = abspath_from_root(config['cacheDirectory'])
+        httpd_config_file = abspath_from_root(config['remoteServer']['httpdConfig'])
+        httpd_pid_file = abspath_from_root(config['remoteServer']['httpdPID'])
+        httpd_error_log_file = abspath_from_root(config['remoteServer']['httpdErroLog'])
+        doc_root = abspath_from_root('public')
+
+        if not os.path.isdir(cache_dir):
+            os.makedirs(cache_dir)
+        os.chmod(cache_dir, 0755)
+
+        httpd_mutax_dir = tempfile.mkdtemp()
+        try:
+            subprocess.call(['httpd',
+                '-f', httpd_config_file,
+                '-c', 'PidFile ' + httpd_pid_file,
+                '-c', 'Mutex file:' + httpd_mutax_dir,
+                '-c', 'DocumentRoot ' + doc_root,
+                '-c', 'ErrorLog ' + httpd_error_log_file,
+                '-X'])
+        finally:
+            os.rmdir(httpd_mutax_dir)
+
+
+def abspath_from_root(relpath):
+    return os.path.abspath(os.path.join(os.path.dirname(__file__), '../', relpath))
+
+
+if __name__ == "__main__":
+    main()