Author: wfarner
Date: Sun Dec 13 17:04:12 2015
New Revision: 1719807

URL: http://svn.apache.org/viewvc?rev=1719807&view=rev
Log:
Clean up markdown translation, now capturing contents of docs/design.

Added:
    aurora/site/publish/documentation/0.10.0/design/
    aurora/site/publish/documentation/0.10.0/design/command-hooks/
    aurora/site/publish/documentation/0.10.0/design/command-hooks/index.html
    aurora/site/publish/documentation/0.5.0-incubating/design/
    aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/
    
aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/index.html
    aurora/site/publish/documentation/0.6.0-incubating/design/
    aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/
    
aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/index.html
    aurora/site/publish/documentation/0.7.0-incubating/design/
    aurora/site/publish/documentation/0.7.0-incubating/design/command-hooks/
    
aurora/site/publish/documentation/0.7.0-incubating/design/command-hooks/index.html
    aurora/site/publish/documentation/0.8.0/design/
    aurora/site/publish/documentation/0.8.0/design/command-hooks/
    aurora/site/publish/documentation/0.8.0/design/command-hooks/index.html
    aurora/site/publish/documentation/0.9.0/design/
    aurora/site/publish/documentation/0.9.0/design/command-hooks/
    aurora/site/publish/documentation/0.9.0/design/command-hooks/index.html
    aurora/site/publish/documentation/latest/design/
    aurora/site/publish/documentation/latest/design/command-hooks/
    aurora/site/publish/documentation/latest/design/command-hooks/index.html
    aurora/site/source/documentation/0.10.0/design/
    aurora/site/source/documentation/0.10.0/design/command-hooks.md
    aurora/site/source/documentation/0.5.0-incubating/design/
    aurora/site/source/documentation/0.5.0-incubating/design/command-hooks.md
    aurora/site/source/documentation/0.6.0-incubating/design/
    aurora/site/source/documentation/0.6.0-incubating/design/command-hooks.md
    aurora/site/source/documentation/0.7.0-incubating/design/
    aurora/site/source/documentation/0.7.0-incubating/design/command-hooks.md
    aurora/site/source/documentation/0.8.0/design/
    aurora/site/source/documentation/0.8.0/design/command-hooks.md
    aurora/site/source/documentation/0.9.0/design/
    aurora/site/source/documentation/0.9.0/design/command-hooks.md
    aurora/site/source/documentation/latest/design/
    aurora/site/source/documentation/latest/design/command-hooks.md
Modified:
    aurora/site/Rakefile
    aurora/site/publish/sitemap.xml

Modified: aurora/site/Rakefile
URL: 
http://svn.apache.org/viewvc/aurora/site/Rakefile?rev=1719807&r1=1719806&r2=1719807&view=diff
==============================================================================
--- aurora/site/Rakefile (original)
+++ aurora/site/Rakefile Sun Dec 13 17:04:12 2015
@@ -30,16 +30,16 @@ task :generate_docs, [:title, :git_tag]
   puts "Generating docs from git tag #{git_tag} with title #{title}"
 
   tmp_dir = File.join(File.dirname(__FILE__), "tmp")
-  Rake::Task[:clean].invoke if File.exist?(tmp_dir)
+  #Rake::Task[:clean].invoke if File.exist?(tmp_dir)
 
   FileUtils.mkdir_p(tmp_dir)
-  puts "Fetching archive of #{git_tag}"
   archive_root = "aurora-#{git_tag}"
   Dir.chdir(tmp_dir) {
     zip_name = "#{git_tag}.zip"
     if File.exist?(zip_name)
       puts 'Skipping archive fetch'
     else
+      puts "Fetching archive of #{git_tag}"
       system("wget https://github.com/apache/aurora/archive/#{zip_name}";)
     end
     if File.exist?(archive_root)
@@ -49,24 +49,24 @@ task :generate_docs, [:title, :git_tag]
     end
   }
 
-  docs_root = File.join(File.dirname(__FILE__), 'source/documentation')
-  docs_in_dir = File.join(tmp_dir, archive_root)
-  docs_out_dir = File.join(docs_root, title)
+  docs_in_dir = File.join(tmp_dir, archive_root, 'docs')
+  docs_out_dir = File.join('source', 'documentation', title)
   FileUtils.rm_f(docs_out_dir)
   FileUtils.mkdir_p(docs_out_dir)
 
+  FileUtils.cp_r(Dir.glob(File.join(docs_in_dir, '*')), docs_out_dir)
+
   puts 'Translating documentation'
-  FileUtils.cp_r(Dir.glob("#{docs_in_dir}/docs/images/"), docs_out_dir)
-  FileUtils.cp_r(Dir.glob("#{docs_in_dir}/docs/*.md"), docs_out_dir)
+  Dir.chdir(docs_out_dir) {
+    FileUtils.mv('README.md', 'index.html.md')
 
-  # Renamd the contributing page.  This doesn't exist in all releases, so we
-  # check first if it exists.
-  contributing_doc = File.join(docs_in_dir, 'CONTRIBUTING.md')
-  if File.exist?(contributing_doc)
-    FileUtils.cp_r("#{docs_in_dir}/CONTRIBUTING.md", 
"#{docs_out_dir}/contributing.md")
-  end
+    # Rename the contributing page to lower case.  This doesn't exist in all 
releases, so we
+    # check first if it exists.
+    contributing_doc = 'CONTRIBUTING.md'
+    if File.exist?(contributing_doc)
+      FileUtils.mv(contributing_doc, contributing_doc.downcase)
+    end
 
-  Dir.chdir("#{docs_out_dir}") {
     Dir.glob('*.md').each { |doc|
       puts "working on: #{doc}"
 
@@ -85,7 +85,6 @@ task :generate_docs, [:title, :git_tag]
       })
     }
   }
-  FileUtils.mv("#{docs_out_dir}/README.md", "#{docs_out_dir}/index.html.md")
 
   puts '!!!!!'
   puts 'Note: If you are adding docs for a new release, you should generate 
with the title "latest" as well.'

Added: aurora/site/publish/documentation/0.10.0/design/command-hooks/index.html
URL: 
http://svn.apache.org/viewvc/aurora/site/publish/documentation/0.10.0/design/command-hooks/index.html?rev=1719807&view=auto
==============================================================================
--- aurora/site/publish/documentation/0.10.0/design/command-hooks/index.html 
(added)
+++ aurora/site/publish/documentation/0.10.0/design/command-hooks/index.html 
Sun Dec 13 17:04:12 2015
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>Apache Aurora</title>
+    <link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css";>
+    <link href="/assets/css/main.css" rel="stylesheet">
+       <!-- Analytics -->
+       <script type="text/javascript">
+                 var _gaq = _gaq || [];
+                 _gaq.push(['_setAccount', 'UA-45879646-1']);
+                 _gaq.push(['_setDomainName', 'apache.org']);
+                 _gaq.push(['_trackPageview']);
+
+                 (function() {
+                   var ga = document.createElement('script'); ga.type = 
'text/javascript'; ga.async = true;
+                   ga.src = ('https:' == document.location.protocol ? 
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+                   var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);
+                 })();
+       </script>
+  </head>
+  <body>
+    <div class="container-fluid section-header">
+  <div class="container">
+    <div class="nav nav-bar">
+    <a href="/"><img src="/assets/img/aurora_logo_dkbkg.svg" width="300" 
alt="Transparent Apache Aurora logo with dark background"/></a>
+    <ul class="nav navbar-nav navbar-right">
+      <li><a href="/documentation/latest/">Documentation</a></li>
+      <li><a href="/community/">Community</a></li>
+      <li><a href="/downloads/">Downloads</a></li>
+      <li><a href="/blog/">Blog</a></li>
+    </ul>
+    </div>
+  </div>
+</div>
+       
+    <div class="container-fluid">
+      <div class="container content">
+        <div class="col-md-12 documentation">
+<h5 class="page-header text-uppercase">Documentation</h5>
+<select onChange="window.location.href='/documentation/' + this.value">
+  <option value="0.10.0">
+    0.10.0
+      (latest)
+  </option>
+  <option value="0.9.0">
+    0.9.0
+  </option>
+  <option value="0.8.0">
+    0.8.0
+  </option>
+  <option value="0.7.0-incubating">
+    0.7.0-incubating
+  </option>
+  <option value="0.6.0-incubating">
+    0.6.0-incubating
+  </option>
+  <option value="0.5.0-incubating">
+    0.5.0-incubating
+  </option>
+</select>
+
+<h1 id="command-hooks-for-the-aurora-client">Command Hooks for the Aurora 
Client</h1>
+
+<h2 id="introduction-motivation">Introduction/Motivation</h2>
+
+<p>We&rsquo;ve got hooks in the client that surround API calls. These are
+pretty awkward, because they don&rsquo;t correlate with user actions. For
+example, suppose we wanted a policy that said users weren&rsquo;t allowed to
+kill all instances of a production job at once.</p>
+
+<p>Right now, all that we could hook would be the &ldquo;killJob&rdquo; api 
call. But
+kill (at least in newer versions of the client) normally runs in
+batches. If a user called killall, what we would see on the API level
+is a series of &ldquo;killJob&rdquo; calls, each of which specified a batch of
+instances. We woudn&rsquo;t be able to distinguish between really killing
+all instances of a job (which is forbidden under this policy), and
+carefully killing in batches (which is permitted.) In each case, the
+hook would just see a series of API calls, and couldn&rsquo;t find out what
+the actual command being executed was!</p>
+
+<p>For most policy enforcement, what we really want to be able to do is
+look at and vet the commands that a user is performing, not the API
+calls that the client uses to implement those commands.</p>
+
+<p>So I propose that we add a new kind of hooks, which surround noun/verb
+commands. A hook will register itself to handle a collection of (noun,
+verb) pairs. Whenever any of those noun/verb commands are invoked, the
+hooks methods will be called around the execution of the verb. A
+pre-hook will have the ability to reject a command, preventing the
+verb from being executed.</p>
+
+<h2 id="registering-hooks">Registering Hooks</h2>
+
+<p>These hooks will be registered via configuration plugins. A configuration 
plugin
+can register hooks using an API. Hooks registered this way are, effectively,
+hardwired into the client executable.</p>
+
+<p>The order of execution of hooks is unspecified: they may be called in
+any order. There is no way to guarantee that one hook will execute
+before some other hook.</p>
+
+<h3 id="global-hooks">Global Hooks</h3>
+
+<p>Commands registered by the python call are called <em>global</em> hooks,
+because they will run for all configurations, whether or not they
+specify any hooks in the configuration file.</p>
+
+<p>In the implementation, hooks are registered in the module
+<code>apache.aurora.client.cli.command_hooks</code>, using the class
+<code>GlobalCommandHookRegistry</code>. A global hook can be registered by 
calling
+<code>GlobalCommandHookRegistry.register_command_hook</code> in a 
configuration plugin.</p>
+
+<h3 id="the-api">The API</h3>
+<pre class="highlight objective_c"><code><span style="background-color: 
#f8f8f8">class</span> <span style="background-color: 
#f8f8f8">CommandHook</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">object</span><span 
style="background-color: #f8f8f8">)</span>
+  <span style="color: #000000;font-weight: bold">@property</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">name</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Returns a name for the hook."</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_nouns</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the nouns that have verbs that should 
invoke this hook."""</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_verbs</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the verbs for a particular noun that 
should invoke his hook."""</span>
+
+  <span style="color: #a61717;background-color: #e3d2d2">@abstractmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">pre_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook before invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: True if the command should be 
allowed to proceed; False if the command</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    should be rejected.</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">post_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">result</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook after invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * result: the result code returned by the 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: nothing</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+<span style="background-color: #f8f8f8">class</span> <span 
style="background-color: #f8f8f8">GlobalCommandHookRegistry</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">object</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+  <span style="color: #a61717;background-color: #e3d2d2">@classmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">register_command_hook</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">hook</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="background-color: #f8f8f8">pass</span>
+</code></pre>
+
+<h3 id="skipping-hooks">Skipping Hooks</h3>
+
+<p>To skip a hook, a user uses a command-line option, 
<code>--skip-hooks</code>. The option can either
+specify specific hooks to skip, or &ldquo;all&rdquo;:</p>
+
+<ul>
+<li><code>aurora --skip-hooks=all job create east/bozo/devel/myjob</code> will 
create a job
+without running any hooks.</li>
+<li><code>aurora --skip-hooks=test,iq create east/bozo/devel/myjob</code> will 
create a job,
+and will skip only the hooks named &ldquo;test&rdquo; and 
&ldquo;iq&rdquo;.</li>
+</ul>
+
+</div>
+
+      </div>
+    </div>
+       <div class="container-fluid section-footer buffer">
+      <div class="container">
+        <div class="row">
+                 <div class="col-md-2 col-md-offset-1"><h3>Quick Links</h3>
+                 <ul>
+                   <li><a href="/downloads/">Downloads</a></li>
+            <li><a href="/community/">Mailing Lists</a></li>
+                       <li><a 
href="http://issues.apache.org/jira/browse/AURORA";>Issue Tracking</a></li>
+                       <li><a href="/documentation/latest/contributing/">How 
To Contribute</a></li>     
+                 </ul>
+             </div>
+                 <div class="col-md-2"><h3>The ASF</h3>
+          <ul>
+            <li><a href="http://www.apache.org/licenses/";>License</a></li>
+            <li><a 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li>  
+            <li><a 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li>
+            <li><a href="http://www.apache.org/security/";>Security</a></li>
+          </ul>
+                 </div>
+                 <div class="col-md-6">
+                       <p class="disclaimer">Copyright 2014 <a 
href="http://www.apache.org/";>Apache Software Foundation</a>. Licensed under 
the <a href="http://www.apache.org/licenses/";>Apache License v2.0</a>. The <a 
href="https://www.flickr.com/photos/trondk/12706051375/";>Aurora Borealis IX 
photo</a> displayed on the homepage is available under a <a 
href="https://creativecommons.org/licenses/by-nc-nd/2.0/";>Creative Commons 
BY-NC-ND 2.0 license</a>. Apache, Apache Aurora, and the Apache feather logo 
are trademarks of The Apache Software Foundation.</p>
+        </div>
+      </div>
+    </div>
+
+  </body>
+</html>

Added: 
aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/index.html
URL: 
http://svn.apache.org/viewvc/aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/index.html?rev=1719807&view=auto
==============================================================================
--- 
aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/index.html
 (added)
+++ 
aurora/site/publish/documentation/0.5.0-incubating/design/command-hooks/index.html
 Sun Dec 13 17:04:12 2015
@@ -0,0 +1,360 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>Apache Aurora</title>
+    <link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css";>
+    <link href="/assets/css/main.css" rel="stylesheet">
+       <!-- Analytics -->
+       <script type="text/javascript">
+                 var _gaq = _gaq || [];
+                 _gaq.push(['_setAccount', 'UA-45879646-1']);
+                 _gaq.push(['_setDomainName', 'apache.org']);
+                 _gaq.push(['_trackPageview']);
+
+                 (function() {
+                   var ga = document.createElement('script'); ga.type = 
'text/javascript'; ga.async = true;
+                   ga.src = ('https:' == document.location.protocol ? 
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+                   var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);
+                 })();
+       </script>
+  </head>
+  <body>
+    <div class="container-fluid section-header">
+  <div class="container">
+    <div class="nav nav-bar">
+    <a href="/"><img src="/assets/img/aurora_logo_dkbkg.svg" width="300" 
alt="Transparent Apache Aurora logo with dark background"/></a>
+    <ul class="nav navbar-nav navbar-right">
+      <li><a href="/documentation/latest/">Documentation</a></li>
+      <li><a href="/community/">Community</a></li>
+      <li><a href="/downloads/">Downloads</a></li>
+      <li><a href="/blog/">Blog</a></li>
+    </ul>
+    </div>
+  </div>
+</div>
+       
+    <div class="container-fluid">
+      <div class="container content">
+        <div class="col-md-12 documentation">
+<h5 class="page-header text-uppercase">Documentation</h5>
+<select onChange="window.location.href='/documentation/' + this.value">
+  <option value="0.10.0">
+    0.10.0
+      (latest)
+  </option>
+  <option value="0.9.0">
+    0.9.0
+  </option>
+  <option value="0.8.0">
+    0.8.0
+  </option>
+  <option value="0.7.0-incubating">
+    0.7.0-incubating
+  </option>
+  <option value="0.6.0-incubating">
+    0.6.0-incubating
+  </option>
+  <option value="0.5.0-incubating">
+    0.5.0-incubating
+  </option>
+</select>
+
+<h1 id="command-hooks-for-the-aurora-client">Command Hooks for the Aurora 
Client</h1>
+
+<h2 id="introduction-motivation">Introduction/Motivation</h2>
+
+<p>We&rsquo;ve got hooks in the client that surround API calls. These are
+pretty awkward, because they don&rsquo;t correlate with user actions. For
+example, suppose we wanted a policy that said users weren&rsquo;t allowed to
+kill all instances of a production job at once.</p>
+
+<p>Right now, all that we could hook would be the &ldquo;killJob&rdquo; api 
call. But
+kill (at least in newer versions of the client) normally runs in
+batches. If a user called killall, what we would see on the API level
+is a series of &ldquo;killJob&rdquo; calls, each of which specified a batch of
+instances. We woudn&rsquo;t be able to distinguish between really killing
+all instances of a job (which is forbidden under this policy), and
+carefully killing in batches (which is permitted.) In each case, the
+hook would just see a series of API calls, and couldn&rsquo;t find out what
+the actual command being executed was!</p>
+
+<p>For most policy enforcement, what we really want to be able to do is
+look at and vet the commands that a user is performing, not the API
+calls that the client uses to implement those commands.</p>
+
+<p>So I propose that we add a new kind of hooks, which surround noun/verb
+commands. A hook will register itself to handle a collection of (noun,
+verb) pairs. Whenever any of those noun/verb commands are invoked, the
+hooks methods will be called around the execution of the verb. A
+pre-hook will have the ability to reject a command, preventing the
+verb from being executed.</p>
+
+<h2 id="registering-hooks">Registering Hooks</h2>
+
+<p>These hooks will be registered two ways:
+* Project hooks file. If a file named <code>AuroraHooks</code> is in the 
project directory
+  where an aurora command is being executed, that file will be read,
+  and its hooks will be registered.
+* Configuration plugins. A configuration plugin can register hooks using an 
API.
+  Hooks registered this way are, effectively, hardwired into the client 
executable.</p>
+
+<p>The order of execution of hooks is unspecified: they may be called in
+any order. There is no way to guarantee that one hook will execute
+before some other hook.</p>
+
+<h3 id="global-hooks">Global Hooks</h3>
+
+<p>Commands registered by the python call are called <em>global</em> hooks,
+because they will run for all configurations, whether or not they
+specify any hooks in the configuration file.</p>
+
+<p>In the implementation, hooks are registered in the module
+<code>apache.aurora.client.cli.command_hooks</code>, using the class 
<code>GlobalCommandHookRegistry</code>.  A
+global hook can be registered by calling 
<code>GlobalCommandHookRegistry.register_command_hook</code>
+in a configuration plugin.</p>
+
+<h3 id="hook-files">Hook Files</h3>
+
+<p>A hook file is a file containing Python source code. It will be
+dynamically loaded by the Aurora command line executable. After
+loading, the client will check the module for a global variable named
+&ldquo;hooks&rdquo;, which contains a list of hook objects, which will be 
added to
+the hook registry.</p>
+
+<p>A project hooks file will be named <code>AuroraHooks</code>,
+and will be located in either the directory where the command is being
+executed, or one of its parent directories, up to the nearest git/mercurial
+repository base.</p>
+
+<h3 id="the-api">The API</h3>
+<pre class="highlight objective_c"><code><span style="background-color: 
#f8f8f8">class</span> <span style="background-color: 
#f8f8f8">CommandHook</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">object</span><span 
style="background-color: #f8f8f8">)</span>
+  <span style="color: #000000;font-weight: bold">@property</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">name</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Returns a name for the hook."</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_nouns</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the nouns that have verbs that should 
invoke this hook."""</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_verbs</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the verbs for a particular noun that 
should invoke his hook."""</span>
+
+  <span style="color: #a61717;background-color: #e3d2d2">@abstractmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">pre_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook before invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: True if the command should be 
allowed to proceed; False if the command</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    should be rejected.</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">post_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">result</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook after invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * result: the result code returned by the 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: nothing</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+<span style="background-color: #f8f8f8">class</span> <span 
style="background-color: #f8f8f8">GlobalCommandHookRegistry</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">object</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+  <span style="color: #a61717;background-color: #e3d2d2">@classmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">register_command_hook</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">hook</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="background-color: #f8f8f8">pass</span>
+</code></pre>
+
+<h2 id="skipping-hooks">Skipping Hooks</h2>
+
+<p>In a perfect world, hooks would represent a global property or policy
+that should always be enforced. Unfortunately, we don&rsquo;t live in a
+perfect world, which means that sometimes, every rule needs to get
+broken.</p>
+
+<p>For example, an organization could decide that every configuration
+must be checked in to source control before it could be
+deployed. That&rsquo;s an entirely reasonable policy. It would be easy to
+implement it using a hook. But what if there&rsquo;s a problem, and the
+source repos is down?</p>
+
+<p>The easiest solution is just to allow a user to add a 
<code>--skip-hooks</code>
+flag to the command-line. But doing that means that an organization
+can&rsquo;t actually use hooks to enforce policy, because users can skip
+them whenever they want.</p>
+
+<p>Instead, we&rsquo;d like to have a system where it&rsquo;s possible to 
create
+hooks to enforce policy, and then include a way of building policy
+about when hooks can be skipped.</p>
+
+<p>I&rsquo;m using sudo as a rough model for this. Many organizations need to
+give people the ability to run privileged commands, but they still
+want to have some control. Sudo allows them to specify who is allowed
+to run a privileged command; where they&rsquo;re allowed to run it; and what
+command(s) they&rsquo;re allowed to run.  All of that is specified in a
+special system file located in <code>/etc/sudoers</code> on a typical unix
+machine.</p>
+
+<p>In a world of distributed systems, this approach has one grave
+weakness. An aurora client can be located on any machine that has
+network access to a Mesos/Aurora cluster. It can be run by a user in
+pretty much any way they want - from a machine they control, from a
+special chroot they created, etc. Relying an a file being in a special
+location on their machine isn&rsquo;t sufficient - it&rsquo;s too easy to
+maliciously or erroneously run a command in an environment with an
+invalid hooks exceptions file.</p>
+
+<p>Instead, we&rsquo;ve got two basic choices: hook exception rules can be
+baked into the client executable, or they can be provided in a
+network location.</p>
+
+<h3 id="specifying-when-hooks-can-be-skipped">Specifying when hooks can be 
skipped</h3>
+
+<h4 id="hooks-file">Hooks File</h4>
+
+<p>The module <code>apache.aurora.client.cli</code> contains a variable named
+<code>GLOBAL_HOOK_SKIP_RULES_URL</code>. In the default distribution of 
Aurora, tihs variable contains
+<code>None</code>. Users can modify this value for their local environments, 
providing
+a site specific URL. If users attempt to bypass command hooks, and this
+URL is not <code>None</code>, then the client will fetch the contents of that 
URL, and
+attempt to interpret it as a hooks exception file.</p>
+
+<p>The hooks exception file is written in JSON, with the following 
structure:</p>
+<pre class="highlight json"><code><span style="background-color: 
#f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: 
#000080">"rulename"</span><span style="background-color: #f8f8f8">:</span><span 
style="color: #bbbbbb">
+  </span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb">
+  </span><span style="color: #000080">"hooks"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #d14">"hook-name "</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">],</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">string</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">...</span><span style="background-color: #f8f8f8">],</span><span 
style="color: #bbbbbb">
+  </span><span style="color: #000080">"commands"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"job"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"kill"</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #d14">"killall"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">}</span><span style="background-color: 
 #f8f8f8">,</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"arg-patterns"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #d14">"regexp-str"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb">
+  </span><span style="background-color: #f8f8f8">},</span><span style="color: 
#bbbbbb">
+  </span><span style="color: #a61717;background-color: 
#e3d2d2">...</span><span style="color: #bbbbbb">
+</span><span style="color: #a61717;background-color: #e3d2d2">}</span><span 
style="color: #bbbbbb">
+</span></code></pre>
+
+<ul>
+<li><code>hooks</code> is a list of hook identifiers which can be skipped by a 
user
+that satisfies this rule. If omitted, then this rule applies to <em>all 
hooks</em>.
+(Omitting the <code>hooks</code> field is equivalent to giving it the value 
<code>[&#39;*&#39;]</code>.)</li>
+<li><code>users</code> is a list of user names, or glob expressions that range 
over user
+names. This rule gives permission to those users to skip hooks. If omitted,
+then this rule allows <em>any user</em> to skip hooks that satisfy the rest of 
this rule.
+Note that this is <em>user</em> names, not
+<em>role</em> names: the rules specify users that are allowed to skip commands.
+Some users that are allowed to work with a role account may be allowed to
+skip, while others cannot.</li>
+<li><code>commands</code> is a map from nouns to lists of verbs. If a command 
<code>aurora n v</code>
+is being executed, this rule allows the hooks to be skipped if
+<code>v</code> is in <code>commands[n]</code>. If this is omitted, then it 
allows hooks to be skipped for all
+commands that satisfy the rest of the rule.</li>
+<li><code>arg_patterns</code> is a list of glob patterns ranging over 
parameters.
+If any of the parameters of the command match the parameters in this list,
+the hook can be skipped. If ommitted, then this applies regardless of 
arguments.</li>
+</ul>
+
+<p>For example, the following is a hook rules file which allows:
+* The user &ldquo;root&rdquo; to skip any hook.
+* Any user to skip hooks for test jobs.
+* A specific group of users to skip hooks for jobs in cluster <code>east</code>
+* Another group of users to skip hooks for <code>job kill</code> in cluster 
<code>west</code>.</p>
+<pre class="highlight json"><code><span style="background-color: 
#f8f8f8">{</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-admin"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"root"</span><span style="background-color: #f8f8f8">]</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-test"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"\*"</span><span style="background-color: #f8f8f8">],</span><span 
style="color: #bbbbbb"> </span><span style="color: 
#000080">"arg-patterns"</span><span style="background-color: 
#f8f8f8">:</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"\*/\*/test/\*"</span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-east-users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span style="color: 
#a61717;background-color: #e3d2d2">=['john',</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">'mary',</span><span style="color: #bbbbbb"> </span><span style="color: 
#a61717;background-color: #e3d2d2">'mike',</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: 
#e3d2d2">'sue'],</span><span style="color: #bbbbbb">
+      </span><span style="color: #000080">"arg-patterns"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"east/\*/\*/\*"</span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-west-kills"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"anne"</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #d14">"bill"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #d14">"chris"</span><span style="background-color: 
#f8f8f8">],</span><span style="color: #bbbbbb">
+      </span><span style="color: #000080">"commands"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"job"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"kill"</span><span style="background-color: #f8f8f8">]},</span><span 
style="color: #bbbbbb"> </span><span style="color: 
#000080">"arg-patterns"</span><span style="color: #bbbbbb"> </span><span 
style="color: #a61717;background-color: #e3d2d2">=</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">[</span><span style="color: #000080">"west/\*/\*/\*"</span><span 
style="color: #a61717;background-color: #e3d2d2">]</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">}</span><spa
 n style="color: #bbbbbb">
+</span><span style="background-color: #f8f8f8">}</span><span style="color: 
#bbbbbb">
+</span></code></pre>
+
+<h4 id="programmatic-hooks-exceptions">Programmatic Hooks Exceptions</h4>
+
+<p>The <code>GlobalHooksRegistry</code> contains the method 
<code>add_hooks_exception</code>, which allows
+users to register local hooks exceptions using the 
<code>ConfigurationPlugin</code> mechanism.
+A hooks exception object implements the following interface:</p>
+<pre class="highlight plaintext"><code>class HooksException(object):
+  def allow_exception(self, hooks, role, noun, verb, args):
+    """Params:
+    - hooks: a list of hook-names that the user wants to skip. If this
+      is ommitted, then this applies to all hooks.
+    - role: the role requesting that hooks be skipped.
+    - noun, verb: the noun and verb being executed.
+    - the other command-line arguments.
+    Returns: True if the user should be allowed to skip the requested hooks.
+    """
+    return False
+</code></pre>
+
+<p>When a user supplies the <code>--skip-hooks</code> argument, 
<code>allow_exception</code> is invoked on
+each of the <code>HooksException</code> arguments. If <em>any</em> of the 
hooks exception objects
+returns <code>True</code>, then the user will be permitted to skip the 
hooks.</p>
+
+<h3 id="skipping-hooks">Skipping Hooks</h3>
+
+<p>To skip a hook, a user uses a command-line option, 
<code>--skip-hooks</code>. The option can either
+specify specific hooks to skip, or &ldquo;all&rdquo;:</p>
+
+<ul>
+<li><code>aurora --skip-hooks=all job create east/bozo/devel/myjob</code> will 
create a job
+without running any hooks.</li>
+<li><code>aurora --skip-hooks=test,iq create east/bozo/devel/myjob</code> will 
create a job,
+and will skip only the hooks named &ldquo;test&rdquo; and 
&ldquo;iq&rdquo;.</li>
+</ul>
+
+<h2 id="changes">Changes</h2>
+
+<p>4/30:
+* Rule exceptions are defined in JSON, and they are specified to be loaded from
+  a URL, not from a local file.
+* Rule exceptions specify users, not roles.</p>
+
+<p>4/27:
+Major changes between this and the last version of this proposal.
+* Command hooks can&rsquo;t be declared in a configuration file. There&rsquo;s 
a simple
+  reason why: hooks run before a command&rsquo;s implementation is invoked.
+  Config files are read during the commands invocation if necessary. If the
+  hook is declared in the config file, by the time you know that it should
+  have been run, it&rsquo;s too late. So I&rsquo;ve removed config-hooks from 
the
+  proposal. (API hooks defined by configs still work.)
+* Skipping hooks. We expect aurora to be used inside of large
+  organizations. One of the primary use-cases of hooks is to create
+  enforcable policy that are specific to an organization. If hooks
+  can just be skipped because a user wants to skip them, it means that
+  the policy can&rsquo;t be enforced, which defeats the purpose of having them.
+  So in this update, I propose a mechanism, loosely based on a 
<code>sudo</code>-like
+  mechanism for defining when hooks can be skipped.</p>
+
+</div>
+
+      </div>
+    </div>
+       <div class="container-fluid section-footer buffer">
+      <div class="container">
+        <div class="row">
+                 <div class="col-md-2 col-md-offset-1"><h3>Quick Links</h3>
+                 <ul>
+                   <li><a href="/downloads/">Downloads</a></li>
+            <li><a href="/community/">Mailing Lists</a></li>
+                       <li><a 
href="http://issues.apache.org/jira/browse/AURORA";>Issue Tracking</a></li>
+                       <li><a href="/documentation/latest/contributing/">How 
To Contribute</a></li>     
+                 </ul>
+             </div>
+                 <div class="col-md-2"><h3>The ASF</h3>
+          <ul>
+            <li><a href="http://www.apache.org/licenses/";>License</a></li>
+            <li><a 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li>  
+            <li><a 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li>
+            <li><a href="http://www.apache.org/security/";>Security</a></li>
+          </ul>
+                 </div>
+                 <div class="col-md-6">
+                       <p class="disclaimer">Copyright 2014 <a 
href="http://www.apache.org/";>Apache Software Foundation</a>. Licensed under 
the <a href="http://www.apache.org/licenses/";>Apache License v2.0</a>. The <a 
href="https://www.flickr.com/photos/trondk/12706051375/";>Aurora Borealis IX 
photo</a> displayed on the homepage is available under a <a 
href="https://creativecommons.org/licenses/by-nc-nd/2.0/";>Creative Commons 
BY-NC-ND 2.0 license</a>. Apache, Apache Aurora, and the Apache feather logo 
are trademarks of The Apache Software Foundation.</p>
+        </div>
+      </div>
+    </div>
+
+  </body>
+</html>

Added: 
aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/index.html
URL: 
http://svn.apache.org/viewvc/aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/index.html?rev=1719807&view=auto
==============================================================================
--- 
aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/index.html
 (added)
+++ 
aurora/site/publish/documentation/0.6.0-incubating/design/command-hooks/index.html
 Sun Dec 13 17:04:12 2015
@@ -0,0 +1,360 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>Apache Aurora</title>
+    <link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css";>
+    <link href="/assets/css/main.css" rel="stylesheet">
+       <!-- Analytics -->
+       <script type="text/javascript">
+                 var _gaq = _gaq || [];
+                 _gaq.push(['_setAccount', 'UA-45879646-1']);
+                 _gaq.push(['_setDomainName', 'apache.org']);
+                 _gaq.push(['_trackPageview']);
+
+                 (function() {
+                   var ga = document.createElement('script'); ga.type = 
'text/javascript'; ga.async = true;
+                   ga.src = ('https:' == document.location.protocol ? 
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+                   var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);
+                 })();
+       </script>
+  </head>
+  <body>
+    <div class="container-fluid section-header">
+  <div class="container">
+    <div class="nav nav-bar">
+    <a href="/"><img src="/assets/img/aurora_logo_dkbkg.svg" width="300" 
alt="Transparent Apache Aurora logo with dark background"/></a>
+    <ul class="nav navbar-nav navbar-right">
+      <li><a href="/documentation/latest/">Documentation</a></li>
+      <li><a href="/community/">Community</a></li>
+      <li><a href="/downloads/">Downloads</a></li>
+      <li><a href="/blog/">Blog</a></li>
+    </ul>
+    </div>
+  </div>
+</div>
+       
+    <div class="container-fluid">
+      <div class="container content">
+        <div class="col-md-12 documentation">
+<h5 class="page-header text-uppercase">Documentation</h5>
+<select onChange="window.location.href='/documentation/' + this.value">
+  <option value="0.10.0">
+    0.10.0
+      (latest)
+  </option>
+  <option value="0.9.0">
+    0.9.0
+  </option>
+  <option value="0.8.0">
+    0.8.0
+  </option>
+  <option value="0.7.0-incubating">
+    0.7.0-incubating
+  </option>
+  <option value="0.6.0-incubating">
+    0.6.0-incubating
+  </option>
+  <option value="0.5.0-incubating">
+    0.5.0-incubating
+  </option>
+</select>
+
+<h1 id="command-hooks-for-the-aurora-client">Command Hooks for the Aurora 
Client</h1>
+
+<h2 id="introduction-motivation">Introduction/Motivation</h2>
+
+<p>We&rsquo;ve got hooks in the client that surround API calls. These are
+pretty awkward, because they don&rsquo;t correlate with user actions. For
+example, suppose we wanted a policy that said users weren&rsquo;t allowed to
+kill all instances of a production job at once.</p>
+
+<p>Right now, all that we could hook would be the &ldquo;killJob&rdquo; api 
call. But
+kill (at least in newer versions of the client) normally runs in
+batches. If a user called killall, what we would see on the API level
+is a series of &ldquo;killJob&rdquo; calls, each of which specified a batch of
+instances. We woudn&rsquo;t be able to distinguish between really killing
+all instances of a job (which is forbidden under this policy), and
+carefully killing in batches (which is permitted.) In each case, the
+hook would just see a series of API calls, and couldn&rsquo;t find out what
+the actual command being executed was!</p>
+
+<p>For most policy enforcement, what we really want to be able to do is
+look at and vet the commands that a user is performing, not the API
+calls that the client uses to implement those commands.</p>
+
+<p>So I propose that we add a new kind of hooks, which surround noun/verb
+commands. A hook will register itself to handle a collection of (noun,
+verb) pairs. Whenever any of those noun/verb commands are invoked, the
+hooks methods will be called around the execution of the verb. A
+pre-hook will have the ability to reject a command, preventing the
+verb from being executed.</p>
+
+<h2 id="registering-hooks">Registering Hooks</h2>
+
+<p>These hooks will be registered two ways:
+* Project hooks file. If a file named <code>AuroraHooks</code> is in the 
project directory
+  where an aurora command is being executed, that file will be read,
+  and its hooks will be registered.
+* Configuration plugins. A configuration plugin can register hooks using an 
API.
+  Hooks registered this way are, effectively, hardwired into the client 
executable.</p>
+
+<p>The order of execution of hooks is unspecified: they may be called in
+any order. There is no way to guarantee that one hook will execute
+before some other hook.</p>
+
+<h3 id="global-hooks">Global Hooks</h3>
+
+<p>Commands registered by the python call are called <em>global</em> hooks,
+because they will run for all configurations, whether or not they
+specify any hooks in the configuration file.</p>
+
+<p>In the implementation, hooks are registered in the module
+<code>apache.aurora.client.cli.command_hooks</code>, using the class 
<code>GlobalCommandHookRegistry</code>.  A
+global hook can be registered by calling 
<code>GlobalCommandHookRegistry.register_command_hook</code>
+in a configuration plugin.</p>
+
+<h3 id="hook-files">Hook Files</h3>
+
+<p>A hook file is a file containing Python source code. It will be
+dynamically loaded by the Aurora command line executable. After
+loading, the client will check the module for a global variable named
+&ldquo;hooks&rdquo;, which contains a list of hook objects, which will be 
added to
+the hook registry.</p>
+
+<p>A project hooks file will be named <code>AuroraHooks</code>,
+and will be located in either the directory where the command is being
+executed, or one of its parent directories, up to the nearest git/mercurial
+repository base.</p>
+
+<h3 id="the-api">The API</h3>
+<pre class="highlight objective_c"><code><span style="background-color: 
#f8f8f8">class</span> <span style="background-color: 
#f8f8f8">CommandHook</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">object</span><span 
style="background-color: #f8f8f8">)</span>
+  <span style="color: #000000;font-weight: bold">@property</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">name</span><span style="background-color: 
#f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Returns a name for the hook."</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_nouns</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the nouns that have verbs that should 
invoke this hook."""</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">get_verbs</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Return the verbs for a particular noun that 
should invoke his hook."""</span>
+
+  <span style="color: #a61717;background-color: #e3d2d2">@abstractmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">pre_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">)</span><span style="color: 
#000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook before invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: True if the command should be 
allowed to proceed; False if the command</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    should be rejected.</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">post_command</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">noun</span><span style="background-color: 
#f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">commandline</span><span 
style="background-color: #f8f8f8">,</span> <span style="background-color: 
#f8f8f8">result</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+    <span style="color: #d14">"""Execute a hook after invoking a 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * noun: the noun being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * verb: the verb being 
invoked.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * context: the context object that will 
be used to invoke the verb.</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">      The options object will be initialized 
before calling the hook</span><span style="color: #a61717;background-color: 
#e3d2d2">
+</span><span style="color: #d14">    * commandline: the original argv 
collection used to invoke the client.</span><span style="color: 
#a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    * result: the result code returned by the 
verb.</span><span style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    Returns: nothing</span><span 
style="color: #a61717;background-color: #e3d2d2">
+</span><span style="color: #d14">    """</span>
+
+<span style="background-color: #f8f8f8">class</span> <span 
style="background-color: #f8f8f8">GlobalCommandHookRegistry</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">object</span><span style="background-color: #f8f8f8">)</span><span 
style="color: #000000;font-weight: bold">:</span>
+  <span style="color: #a61717;background-color: #e3d2d2">@classmethod</span>
+  <span style="background-color: #f8f8f8">def</span> <span 
style="background-color: #f8f8f8">register_command_hook</span><span 
style="background-color: #f8f8f8">(</span><span style="background-color: 
#f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span 
style="background-color: #f8f8f8">hook</span><span style="background-color: 
#f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span>
+    <span style="background-color: #f8f8f8">pass</span>
+</code></pre>
+
+<h2 id="skipping-hooks">Skipping Hooks</h2>
+
+<p>In a perfect world, hooks would represent a global property or policy
+that should always be enforced. Unfortunately, we don&rsquo;t live in a
+perfect world, which means that sometimes, every rule needs to get
+broken.</p>
+
+<p>For example, an organization could decide that every configuration
+must be checked in to source control before it could be
+deployed. That&rsquo;s an entirely reasonable policy. It would be easy to
+implement it using a hook. But what if there&rsquo;s a problem, and the
+source repos is down?</p>
+
+<p>The easiest solution is just to allow a user to add a 
<code>--skip-hooks</code>
+flag to the command-line. But doing that means that an organization
+can&rsquo;t actually use hooks to enforce policy, because users can skip
+them whenever they want.</p>
+
+<p>Instead, we&rsquo;d like to have a system where it&rsquo;s possible to 
create
+hooks to enforce policy, and then include a way of building policy
+about when hooks can be skipped.</p>
+
+<p>I&rsquo;m using sudo as a rough model for this. Many organizations need to
+give people the ability to run privileged commands, but they still
+want to have some control. Sudo allows them to specify who is allowed
+to run a privileged command; where they&rsquo;re allowed to run it; and what
+command(s) they&rsquo;re allowed to run.  All of that is specified in a
+special system file located in <code>/etc/sudoers</code> on a typical unix
+machine.</p>
+
+<p>In a world of distributed systems, this approach has one grave
+weakness. An aurora client can be located on any machine that has
+network access to a Mesos/Aurora cluster. It can be run by a user in
+pretty much any way they want - from a machine they control, from a
+special chroot they created, etc. Relying an a file being in a special
+location on their machine isn&rsquo;t sufficient - it&rsquo;s too easy to
+maliciously or erroneously run a command in an environment with an
+invalid hooks exceptions file.</p>
+
+<p>Instead, we&rsquo;ve got two basic choices: hook exception rules can be
+baked into the client executable, or they can be provided in a
+network location.</p>
+
+<h3 id="specifying-when-hooks-can-be-skipped">Specifying when hooks can be 
skipped</h3>
+
+<h4 id="hooks-file">Hooks File</h4>
+
+<p>The module <code>apache.aurora.client.cli</code> contains a variable named
+<code>GLOBAL_HOOK_SKIP_RULES_URL</code>. In the default distribution of 
Aurora, tihs variable contains
+<code>None</code>. Users can modify this value for their local environments, 
providing
+a site specific URL. If users attempt to bypass command hooks, and this
+URL is not <code>None</code>, then the client will fetch the contents of that 
URL, and
+attempt to interpret it as a hooks exception file.</p>
+
+<p>The hooks exception file is written in JSON, with the following 
structure:</p>
+<pre class="highlight json"><code><span style="background-color: 
#f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: 
#000080">"rulename"</span><span style="background-color: #f8f8f8">:</span><span 
style="color: #bbbbbb">
+  </span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb">
+  </span><span style="color: #000080">"hooks"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #d14">"hook-name "</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">],</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">string</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">...</span><span style="background-color: #f8f8f8">],</span><span 
style="color: #bbbbbb">
+  </span><span style="color: #000080">"commands"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"job"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"kill"</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #d14">"killall"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">}</span><span style="background-color: 
 #f8f8f8">,</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"arg-patterns"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#bbbbbb"> </span><span style="color: #d14">"regexp-str"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: #e3d2d2">...</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb">
+  </span><span style="background-color: #f8f8f8">},</span><span style="color: 
#bbbbbb">
+  </span><span style="color: #a61717;background-color: 
#e3d2d2">...</span><span style="color: #bbbbbb">
+</span><span style="color: #a61717;background-color: #e3d2d2">}</span><span 
style="color: #bbbbbb">
+</span></code></pre>
+
+<ul>
+<li><code>hooks</code> is a list of hook identifiers which can be skipped by a 
user
+that satisfies this rule. If omitted, then this rule applies to <em>all 
hooks</em>.
+(Omitting the <code>hooks</code> field is equivalent to giving it the value 
<code>[&#39;*&#39;]</code>.)</li>
+<li><code>users</code> is a list of user names, or glob expressions that range 
over user
+names. This rule gives permission to those users to skip hooks. If omitted,
+then this rule allows <em>any user</em> to skip hooks that satisfy the rest of 
this rule.
+Note that this is <em>user</em> names, not
+<em>role</em> names: the rules specify users that are allowed to skip commands.
+Some users that are allowed to work with a role account may be allowed to
+skip, while others cannot.</li>
+<li><code>commands</code> is a map from nouns to lists of verbs. If a command 
<code>aurora n v</code>
+is being executed, this rule allows the hooks to be skipped if
+<code>v</code> is in <code>commands[n]</code>. If this is omitted, then it 
allows hooks to be skipped for all
+commands that satisfy the rest of the rule.</li>
+<li><code>arg_patterns</code> is a list of glob patterns ranging over 
parameters.
+If any of the parameters of the command match the parameters in this list,
+the hook can be skipped. If ommitted, then this applies regardless of 
arguments.</li>
+</ul>
+
+<p>For example, the following is a hook rules file which allows:
+* The user &ldquo;root&rdquo; to skip any hook.
+* Any user to skip hooks for test jobs.
+* A specific group of users to skip hooks for jobs in cluster <code>east</code>
+* Another group of users to skip hooks for <code>job kill</code> in cluster 
<code>west</code>.</p>
+<pre class="highlight json"><code><span style="background-color: 
#f8f8f8">{</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-admin"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"root"</span><span style="background-color: #f8f8f8">]</span><span 
style="color: #bbbbbb"> </span><span style="background-color: 
#f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-test"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"\*"</span><span style="background-color: #f8f8f8">],</span><span 
style="color: #bbbbbb"> </span><span style="color: 
#000080">"arg-patterns"</span><span style="background-color: 
#f8f8f8">:</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"\*/\*/test/\*"</span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-east-users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span style="color: 
#a61717;background-color: #e3d2d2">=['john',</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">'mary',</span><span style="color: #bbbbbb"> </span><span style="color: 
#a61717;background-color: #e3d2d2">'mike',</span><span style="color: #bbbbbb"> 
</span><span style="color: #a61717;background-color: 
#e3d2d2">'sue'],</span><span style="color: #bbbbbb">
+      </span><span style="color: #000080">"arg-patterns"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"east/\*/\*/\*"</span><span style="background-color: 
#f8f8f8">]</span><span style="color: #bbbbbb"> </span><span 
style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
+  </span><span style="color: #000080">"allow-west-kills"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"users"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"anne"</span><span style="background-color: #f8f8f8">,</span><span 
style="color: #bbbbbb"> </span><span style="color: #d14">"bill"</span><span 
style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> 
</span><span style="color: #d14">"chris"</span><span style="background-color: 
#f8f8f8">],</span><span style="color: #bbbbbb">
+      </span><span style="color: #000080">"commands"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">{</span><span style="color: 
#bbbbbb"> </span><span style="color: #000080">"job"</span><span 
style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> 
</span><span style="background-color: #f8f8f8">[</span><span style="color: 
#d14">"kill"</span><span style="background-color: #f8f8f8">]},</span><span 
style="color: #bbbbbb"> </span><span style="color: 
#000080">"arg-patterns"</span><span style="color: #bbbbbb"> </span><span 
style="color: #a61717;background-color: #e3d2d2">=</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">[</span><span style="color: #000080">"west/\*/\*/\*"</span><span 
style="color: #a61717;background-color: #e3d2d2">]</span><span style="color: 
#bbbbbb"> </span><span style="color: #a61717;background-color: 
#e3d2d2">}</span><spa
 n style="color: #bbbbbb">
+</span><span style="background-color: #f8f8f8">}</span><span style="color: 
#bbbbbb">
+</span></code></pre>
+
+<h4 id="programmatic-hooks-exceptions">Programmatic Hooks Exceptions</h4>
+
+<p>The <code>GlobalHooksRegistry</code> contains the method 
<code>add_hooks_exception</code>, which allows
+users to register local hooks exceptions using the 
<code>ConfigurationPlugin</code> mechanism.
+A hooks exception object implements the following interface:</p>
+<pre class="highlight plaintext"><code>class HooksException(object):
+  def allow_exception(self, hooks, role, noun, verb, args):
+    """Params:
+    - hooks: a list of hook-names that the user wants to skip. If this
+      is ommitted, then this applies to all hooks.
+    - role: the role requesting that hooks be skipped.
+    - noun, verb: the noun and verb being executed.
+    - the other command-line arguments.
+    Returns: True if the user should be allowed to skip the requested hooks.
+    """
+    return False
+</code></pre>
+
+<p>When a user supplies the <code>--skip-hooks</code> argument, 
<code>allow_exception</code> is invoked on
+each of the <code>HooksException</code> arguments. If <em>any</em> of the 
hooks exception objects
+returns <code>True</code>, then the user will be permitted to skip the 
hooks.</p>
+
+<h3 id="skipping-hooks">Skipping Hooks</h3>
+
+<p>To skip a hook, a user uses a command-line option, 
<code>--skip-hooks</code>. The option can either
+specify specific hooks to skip, or &ldquo;all&rdquo;:</p>
+
+<ul>
+<li><code>aurora --skip-hooks=all job create east/bozo/devel/myjob</code> will 
create a job
+without running any hooks.</li>
+<li><code>aurora --skip-hooks=test,iq create east/bozo/devel/myjob</code> will 
create a job,
+and will skip only the hooks named &ldquo;test&rdquo; and 
&ldquo;iq&rdquo;.</li>
+</ul>
+
+<h2 id="changes">Changes</h2>
+
+<p>4/30:
+* Rule exceptions are defined in JSON, and they are specified to be loaded from
+  a URL, not from a local file.
+* Rule exceptions specify users, not roles.</p>
+
+<p>4/27:
+Major changes between this and the last version of this proposal.
+* Command hooks can&rsquo;t be declared in a configuration file. There&rsquo;s 
a simple
+  reason why: hooks run before a command&rsquo;s implementation is invoked.
+  Config files are read during the commands invocation if necessary. If the
+  hook is declared in the config file, by the time you know that it should
+  have been run, it&rsquo;s too late. So I&rsquo;ve removed config-hooks from 
the
+  proposal. (API hooks defined by configs still work.)
+* Skipping hooks. We expect aurora to be used inside of large
+  organizations. One of the primary use-cases of hooks is to create
+  enforcable policy that are specific to an organization. If hooks
+  can just be skipped because a user wants to skip them, it means that
+  the policy can&rsquo;t be enforced, which defeats the purpose of having them.
+  So in this update, I propose a mechanism, loosely based on a 
<code>sudo</code>-like
+  mechanism for defining when hooks can be skipped.</p>
+
+</div>
+
+      </div>
+    </div>
+       <div class="container-fluid section-footer buffer">
+      <div class="container">
+        <div class="row">
+                 <div class="col-md-2 col-md-offset-1"><h3>Quick Links</h3>
+                 <ul>
+                   <li><a href="/downloads/">Downloads</a></li>
+            <li><a href="/community/">Mailing Lists</a></li>
+                       <li><a 
href="http://issues.apache.org/jira/browse/AURORA";>Issue Tracking</a></li>
+                       <li><a href="/documentation/latest/contributing/">How 
To Contribute</a></li>     
+                 </ul>
+             </div>
+                 <div class="col-md-2"><h3>The ASF</h3>
+          <ul>
+            <li><a href="http://www.apache.org/licenses/";>License</a></li>
+            <li><a 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li>  
+            <li><a 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li>
+            <li><a href="http://www.apache.org/security/";>Security</a></li>
+          </ul>
+                 </div>
+                 <div class="col-md-6">
+                       <p class="disclaimer">Copyright 2014 <a 
href="http://www.apache.org/";>Apache Software Foundation</a>. Licensed under 
the <a href="http://www.apache.org/licenses/";>Apache License v2.0</a>. The <a 
href="https://www.flickr.com/photos/trondk/12706051375/";>Aurora Borealis IX 
photo</a> displayed on the homepage is available under a <a 
href="https://creativecommons.org/licenses/by-nc-nd/2.0/";>Creative Commons 
BY-NC-ND 2.0 license</a>. Apache, Apache Aurora, and the Apache feather logo 
are trademarks of The Apache Software Foundation.</p>
+        </div>
+      </div>
+    </div>
+
+  </body>
+</html>


Reply via email to