You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by ke...@apache.org on 2014/11/25 23:25:32 UTC

[1/3] incubator-aurora git commit: Extract thrift into an API subproject.

Repository: incubator-aurora
Updated Branches:
  refs/heads/master 5e8058178 -> 91b8d1934


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/aurora/gen/storage.thrift
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/aurora/gen/storage.thrift b/src/main/thrift/org/apache/aurora/gen/storage.thrift
deleted file mode 100644
index 3798797..0000000
--- a/src/main/thrift/org/apache/aurora/gen/storage.thrift
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace java org.apache.aurora.gen.storage
-namespace py gen.apache.aurora.storage
-
-include "api.thrift"
-
-// Thrift object definitions for messages used for mesos storage.
-
-// Ops that are direct representations of the data needed to perform local storage mutations.
-struct SaveFrameworkId {
-  1: string id
-}
-
-struct SaveAcceptedJob {
-  1: string managerId
-  2: api.JobConfiguration jobConfig
-}
-
-struct SaveLock {
-  1: api.Lock lock
-}
-
-struct RemoveLock {
-  1: api.LockKey lockKey
-}
-
-struct RemoveJob {
-  2: api.JobKey jobKey
-}
-
-struct SaveTasks {
-  1: set<api.ScheduledTask> tasks
-}
-
-struct RewriteTask {
-  1: string taskId
-  2: api.TaskConfig task
-}
-
-struct RemoveTasks {
-  1: set<string> taskIds
-}
-
-struct SaveQuota {
-  1: string role
-  2: api.ResourceAggregate quota
-}
-
-struct RemoveQuota {
-  1: string role
-}
-
-struct SaveHostAttributes {
-  1: api.HostAttributes hostAttributes
-}
-
-struct SaveJobUpdate {
-  1: api.JobUpdate jobUpdate
-  2: string lockToken
-}
-
-struct StoredJobUpdateDetails {
-  1: api.JobUpdateDetails details
-  /** ID of the lock associated with this update. */
-  2: string lockToken
-}
-
-struct SaveJobUpdateEvent {
-  1: api.JobUpdateEvent event
-  /** ID of the lock associated with this update. */
-  2: string updateId
-}
-
-struct SaveJobInstanceUpdateEvent {
-  1: api.JobInstanceUpdateEvent event
-  2: string updateId
-}
-
-struct PruneJobUpdateHistory {
-  1: i32 perJobRetainCount
-  2: i64 historyPruneThresholdMs
-}
-
-union Op {
-  1: SaveFrameworkId saveFrameworkId
-  2: SaveAcceptedJob saveAcceptedJob
-  5: RemoveJob removeJob
-  6: SaveTasks saveTasks
-  7: RemoveTasks removeTasks
-  8: SaveQuota saveQuota
-  9: RemoveQuota removeQuota
-  10: SaveHostAttributes saveHostAttributes
-  11: RewriteTask rewriteTask
-  12: SaveLock saveLock
-  13: RemoveLock removeLock
-  14: SaveJobUpdate saveJobUpdate
-  15: SaveJobUpdateEvent saveJobUpdateEvent
-  16: SaveJobInstanceUpdateEvent saveJobInstanceUpdateEvent
-  17: PruneJobUpdateHistory pruneJobUpdateHistory
-}
-
-// The current schema version ID.  This should be incremented each time the
-// schema is changed, and support code for schema migrations should be added.
-const i32 CURRENT_SCHEMA_VERSION = 1
-
-// Represents a series of local storage mutations that should be applied in a single atomic
-// transaction.
-struct Transaction {
-  1: list<Op> ops
-  2: i32 schemaVersion
-}
-
-struct StoredJob {
-  1: string jobManagerId
-  3: api.JobConfiguration jobConfiguration
-}
-
-struct SchedulerMetadata {
-  1: string frameworkId
-  // The SHA of the repo.
-  2: string revision
-  // The tag of the repo.
-  3: string tag
-  // The timestamp of the build.
-  4: string timestamp
-  // The user who built the scheduler
-  5: string user
-  // The machine that built the scheduler
-  6: string machine
-  7: api.APIVersion version
-}
-
-struct QuotaConfiguration {
-  1: string role
-  2: api.ResourceAggregate quota
-}
-
-// Represents a complete snapshot of local storage data suitable for restoring the local storage
-// system to its state at the time the snapshot was taken.
-struct Snapshot {
-
-  // The timestamp when the snapshot was made in milliseconds since the epoch.
-  1: i64 timestamp
-
-  3: set<api.HostAttributes> hostAttributes
-  4: set<api.ScheduledTask> tasks
-  5: set<StoredJob> jobs
-  6: SchedulerMetadata schedulerMetadata
-  8: set<QuotaConfiguration> quotaConfigurations
-  9: set<api.Lock> locks
-  10: set<StoredJobUpdateDetails> jobUpdateDetails
-}
-
-// A message header that calls out the number of expected FrameChunks to follow to form a complete
-// message.
-struct FrameHeader {
-
-  // The number of FrameChunks following this FrameHeader required to reconstitute its message.
-  1: i32 chunkCount
-
-  // The MD5 checksum over the binary blob that was chunked across chunkCount chunks to decompose
-  // the message.
-  2: binary checksum
-}
-
-// A chunk of binary data that can be assembled with others to reconstitute a fully framed message.
-struct FrameChunk {
-  2: binary data
-}
-
-// Frames form a series of LogEntries that can be re-assembled into a basic log entry type like a
-// Snapshot.  The Frame protocol is that a single FrameHeader is followed by one or more FrameChunks
-// that can be re-assembled to obtain the binary content of a basic log entry type.
-//
-// In the process of reading a Frame, invalid data should always be logged and skipped as it may
-// represent a failed higher level transaction where a FrameHeader successfully appends but not all
-// the chunks required to complete the full message frame successfully commit.  For example: if a
-// Snaphsot is framed, it might break down into 1 FrameHeader followed by 5 FrameChunks.  It could
-// be that the FrameHeader and 2 chunks get written successfully, but the 3rd and subsequent chunks
-// fail to append.  In this case, the storage mechanism would throw to indicate a failed transaction
-// at write-time leaving a partially framed message in the log stream that should be skipped over at
-// read-time.
-union Frame {
-  1: FrameHeader header
-  2: FrameChunk chunk
-}
-
-// A ScheduledTask with its assignedTask.task field set to null. Deserializers must fill in
-// assignedTask.task with the TaskConfig identified by taskConfigId (which is an index into the
-// DeduplicatedSnapshot's taskConfigs list).
-struct DeduplicatedScheduledTask {
-  1: api.ScheduledTask partialScheduledTask
-  2: i32 taskConfigId
-}
-
-// A Snapshot that has had duplicate TaskConfig structs removed to save space. The
-// partialSnapshot field is a normal Snapshot with the tasks field set to null. To create the
-// full Snapshot deserializers must fill in this field with the result of recreating each
-// partial task using the referenced entry in taskConfigs.
-struct DeduplicatedSnapshot {
-   // Snapshot with its tasks field unset.
-   1: Snapshot partialSnapshot
-   // ScheduledTasks that have had their assignedTask.task field replaced with an ID to save space.
-   2: list<DeduplicatedScheduledTask> partialTasks
-   // Ordered list of taskConfigs. The taskConfigId field of DeduplicatedScheduledTask is an index
-   // into this.
-   3: list<api.TaskConfig> taskConfigs
-}
-
-// A scheduler storage write-ahead log entry consisting of no-ops to skip over or else snapshots or
-// transactions to apply.  Any entry type can also be chopped up into frames if the entry is too big
-// for whatever reason.
-union LogEntry {
-  // The full state of the scheduler at some point-in-time. Transactions appearing before this
-  // entry in the log can be ignored.
-  1: Snapshot snapshot
-
-  // An incremental update to apply to the scheduler storage.
-  2: Transaction transaction
-
-  // The value should be ignored - both true and false signal an equivalent no operation marker.
-  3: bool noop;
-
-  // A frame that can be reassembled with others to form a complete LogEntry.
-  4: Frame frame
-
-  // A LogEntry that is first serialized in the thrift binary format,
-  // then compressed using the "deflate" compression format.
-  // Deflated entries are expected to be un-framed.  They may be pieced together by multiple frames,
-  // but the contents of the deflated entry should not be a Frame.
-  5: binary deflatedEntry
-
-  // The full state of the scheduler at some point-in-time, in a compact layout. Transactions
-  // appearing before this entry in the log can be ignored.
-  6: DeduplicatedSnapshot deduplicatedSnapshot
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/aurora/gen/test.thrift
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/aurora/gen/test.thrift b/src/main/thrift/org/apache/aurora/gen/test.thrift
deleted file mode 100644
index cd08f28..0000000
--- a/src/main/thrift/org/apache/aurora/gen/test.thrift
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace java org.apache.aurora.gen.test
-namespace py gen.apache.aurora.test
-
-// Test data for Thrift interface definition for the Twitter Mesos Scheduler.
-
-// Test data for job path identifiers.
-const set<string> VALID_IDENTIFIERS = ["devel",
-                                       "dev-prod",
-                                       "Dev_prod-",
-                                       "deV.prod",
-                                       ".devprod.."]
-
-const set<string> INVALID_IDENTIFIERS = ["dev/prod",
-                                         "dev prod",
-                                         "/dev/prod",
-                                         "///",
-                                         "new\nline",
-                                         "    hello world."]
-
-
-// Valid cron schedules (taken from a list of cron schedules running at Twitter).
-const set<string> VALID_CRON_SCHEDULES = [
-    "25 */2 * * *",
-    "05 */1 * * *",
-    "5 */4 * * *",
-    "42 * * * *",
-    "30 07 * * *",
-    "28 23 * * 3",
-    "11 * * * *",
-    "23 */2 * * *",
-    "10,40 8,9,10,11 * * *",
-    "22 * * * *",
-    "15 8,13,18 * * *",
-    "15,45 * * * *",
-    "0 */1 * * *",
-    "02 6 * * *",
-    "1 * * * *",
-    "37 */1 * * *",
-    "0 0/3 * * *",
-    "19 12,23 * * *",
-    "41 4,12,20 * * *",
-    "16 09,16 * * *",
-    "17 1,9,17 * * 0",
-    "*/1 * * * *",
-    "0 17,23 * * *",
-    "42 18,21,23,3,7 * * *",
-    "20 12 * * *",
-    "3,13,23,33,43,53 * * * *",
-    "50 07 * * *",
-    "00 22 * * 0,2,5",
-    "6 2,10,18 * * *",
-    "59 */4 * * *",
-    "17 00 * * *",
-    "10 06 * * *",
-    "13,28,43,58 * * * *",
-    "0 */3 * * *",
-    "0 2 * * *",
-    "30 * * * *",
-    "0 8,11,14,17,20 * * *",
-    "10 * * * *",
-    "30 06 * * *",
-    "23 * * * *",
-    "30 9 * * *",
-    "02 6,10,14 * * *",
-    "19 * * * *",
-    "7 12 * * *",
-    "0 * * * *",
-    "*/10 * * * *",
-    "30 14,16,18,20,22 * * *",
-    "0,10,20,30,40,50 * * * *",
-    "30 0,12 * * *",
-    "45 22 * * *",
-    "20 */3 * * *",
-    "14 9,21 * * *",
-    "*/20 * * * *",
-    "1 7,15,23 * * *",
-    "*/2 * * * *",
-    "25 14 * * *",
-    "0 */6 * * *",
-    "30 6 * * *",
-    "0 16,20,0,3,6 * * *",
-    "5,15,25,35,45,55 * * * *",
-    "22 3,15 * * *",
-    "0 1,3,5,7,9,11,13 * * *",
-    "14 8,17 * * *",
-    "30 21 * * 0,2,5",
-    "44 23 * * *",
-    "35,50 * * * *",
-    "10 01,07,13,19 * * *",
-    "1 14 * * *",
-    "29 9,16,22 * * *",
-    "12 2 * * *",
-    "0 22 * * *",
-    "1 */6 * * *",
-    "0 20 * * 4",
-    "0 9,12,15,18,21 * * *",
-    "30 2 * * *",
-    "15 * * * *",
-    "0 20 * * 1",
-    "0 */12 * * *",
-    "17 0,5,17,20 * * *",
-    "0 20 * * *",
-    "30 18,23 * * MON-FRI",
-    "0 22 * * 1",
-    "35 23 * * *",
-    "55 03 * * *",
-    "23 3,15,22 * * *",
-    "20 13 * * *",
-    "30 11 * * *",
-    "*/5 * * * *",
-    "*/6 * * * *",
-    "0 2,4,6,8,10,12 * * *",
-    "10 02,08,12 * * *",
-    "0 11 * * *",
-    "05 02,08,12 * * *",
-    "10 11 * * *",
-    "22 */6 * * *",
-    "00 08 * * *",
-    "0 2 1 * *",
-    "30 19 * * 1,4",
-    "0 */4 * * *",
-    "10,30,50 * * * *",
-    "22 22 * * *",
-    "00 11 * * *",
-    "29 16,17,18,22 * * *",
-    "30 22 * * *",
-    "05 * * * *",
-    "0 23 * * 3",
-    "15 */12 * * *",
-    "30 19 * * 2,5",
-    "*/30 * * * *",
-    "22 6,18 * * *",
-    "0 5 * * *",
-    "15 8 * * 1,3,5",
-    "0 8 * * *",
-    "10 0 * * *",
-    "40 11 * * *",
-    "0 0 * * 1",
-    "17 2,4,11,18 * * *",
-    "30 0,8,16 * * *",
-    "27 8,20 * * *",
-    "0 0 * * *",
-    "20 18 * * 2,4,6",
-    "15 11 * * 2,6",
-    "0,15,30,45 * * * *",
-    "45 * * * *",
-    "36 * * * *",
-    "45 17 * * 0,2,4",
-    "0 */2 * * *",
-    "12 3,15,22 * * *",
-    "2,7,12,17,22,27,32,37,42,47,52,57 * * * *",
-    "0 23 2-31 * *",
-    "10 16 * * *",
-    "3 * * * *",
-    "42 8,20 * * *",
-    "0 15,19,23,2,5 * * *",
-    "30 10 * * *",
-    "2 2 * * *",
-    "0 12 * * *",
-    "15 17 * * *",
-    "0 7 * * *",
-    "1 2 * * *",
-    "30 19 * * 0,3",
-    "15 10 * * 2,6",
-    "55 */1 * * *",
-    "15 */4 * * *",
-    "0 3,6,9,12,15,18,21 * * *",
-    "11 0 * * *",
-    "0 6 * * *",
-    "0 3 * * *",
-    "20 7,12,17 * * *",
-    "21 * * * *",
-    "58 * * * *",
-    "10 02,08,14,20 * * *",
-    "0 1,2,3,4,5,6,7,8,9,10,11,12,13 * * *",
-    "50,59 * * * *",
-    "30,45 18 * * 1",
-    "0 1 * * *",
-    "7 * * * *",
-    "0 14 * * *",
-    "09 22 * * *",
-    "00 17 1-3,5-31 * *",
-    "17 1,9,17 * * 1-6",
-    "45 */4 * * *",
-    "20 2,12,22 * * *",
-    "15 3 * * *",
-    "0 3 1 * *",
-    "42 10 * * *",
-    "12 7 * * *",
-    "1,31 * * * *",
-    "00 01 * * *",
-    "0 9 1 * *",
-    "50 */4 * * *",
-    "43 * * * *",
-    "10,40 9,10,11,12 * * *",
-    "35 * * * *",
-    "8 1,9,17 * * *",
-    "45,54 * * * *",
-    "49 6,18 * * *",
-    "25 12,18,23 * * *",
-    "20 18 * * 1,3,5",
-    "45 17 * * 2,4",
-    "0 17 * * *",
-    "30 */6 * * *",
-    "52 0,6,12,18 * * *",
-    "*/15 * * * *",
-    "1-56/5 * * * *",
-    "0 2,3,4,5,6,7,8,9,10,11,12,13 * * *",
-    "12 * * * *",
-    "*/3 * * * *",
-    "*/4 * * * *",
-    "3 1,9,17 * * *",
-    "00 14 * * *",
-    "10 05 * * *",
-    "8 21 * * *",
-    "0 13 * * 2",
-    "0 13 * * 3",
-    "0 19 * * *",
-    "0 21 * * *",
-    "23 */4 * * *",
-    "10 3,11,19 * * *",
-    "* * * * *",
-    "30 14 * * *",
-    "03,18,33,48 * * * *",
-    "0 11,23 * * *",
-    "30 20 * * 0,2,5",
-    "30 02,08,12 * * *",
-    "45 1,3,5,7,9,11,13,15,17,19,21,23 * * *",
-    "7 */2 * * *",
-    "30 16 * * *",
-    "5 * * * *",
-    "04 06,12,18,23 * * *",
-    "00 */2 * * *",
-    "00 06,15 * * *",
-    "35 */2 * * *",
-    "1 5,13,21 * * *",
-    "47 */2 * * *",
-    "10 21 * * *",
-    "00 21 * * *",
-    "26 2,6,10,14,18,22 * * *",
-    "00 11 * * 0,2,5",
-    "0 18,22 * * MON-FRI",
-    "00 21 * * 0,2,5",
-    "0 17-19 * * 1",
-    "15 9 * * 1,3,5"]

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/thermos/BUILD
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/thermos/BUILD b/src/main/thrift/org/apache/thermos/BUILD
deleted file mode 100644
index d0d789a..0000000
--- a/src/main/thrift/org/apache/thermos/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-
-python_thrift_library(
-  name = 'py-thrift',
-  sources = ['thermos_internal.thrift'],
-  provides = setup_py(
-    name = 'apache.gen.thermos',
-    version = open(os.path.join(get_buildroot(), '.auroraversion')).read().strip().upper(),
-    description = 'Autogenerated Thermos thrift schemas.',
-  )
-)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/thermos/thermos_internal.thrift
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/thermos/thermos_internal.thrift b/src/main/thrift/org/apache/thermos/thermos_internal.thrift
deleted file mode 100644
index 2c449a4..0000000
--- a/src/main/thrift/org/apache/thermos/thermos_internal.thrift
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace py gen.apache.thermos
-
-enum ProcessState {
-  // normal state
-  WAITING   = 0   // blocked on execution dependencies or footprint restrictions
-  FORKED    = 1   // starting, need to wait for signal from Process that it's running
-  RUNNING   = 2   // currently running
-  SUCCESS   = 3   // returncode == 0
-  KILLED    = 4   // Killed by user action or task failure, runner teardown.
-
-  // abnormal states
-  FAILED    = 5   // returncode != 0
-  LOST      = 6   // the coordinator either died or some condition caused us to lose it
-                  // e.g. reboot.
-}
-
-struct ProcessStatus {
-  // Sequence number, must be monotonically increasing for all
-  // ProcessState messages for a particular process across all runs.
-  1: i64             seq
-
-  // Process name
-  3: string          process
-
-  5: ProcessState    state
-
-  // WAITING -> FORKED
- 10: i32             coordinator_pid
- 11: double          fork_time
-
-  // FORKED -> RUNNING
-  6: double          start_time
-  7: i32             pid
-
-  // RUNNING -> {FINISHED, FAILED, KILLED}
-  8: double          stop_time
-  9: i32             return_code
-
-  // {FORKED, RUNNING} -> LOST nothing happens.  this ProcessState ceases to exist.
-  // Doesn't count against the run total.
-}
-
-enum TaskState {
-  ACTIVE     = 0  // Regular plan is being executed
-  CLEANING   = 5  // Regular plan has failed/finished and is being cleaned up
-                  // Existing processes get SIGTERMs.
-                  // Once all processes are finished, => FINALIZING
-                  // If finalization wait overflows, SIGKILL and transition to terminal.
-  FINALIZING = 6  // Finalizing plan is being executed
-  SUCCESS    = 1  // Task has succeeded
-  FAILED     = 2  // Task has failed
-  KILLED     = 3  // Task has been killed
-  LOST       = 4  // Task is lost (special state reserved for garbage collection.)
-}
-
-struct TaskStatus {
-  1: TaskState state
-  2: i64       timestamp_ms
-  3: i32       runner_pid
-  4: i32       runner_uid
-}
-
-// The first framed message in the Ckpt stream.
-struct RunnerHeader {
-  1: string task_id
-  2: i64    launch_time_ms  // kill this
-  3: string sandbox
-  7: string log_dir
-  4: string hostname        // kill this
-  5: string user
-  8: i32    uid             // added as a check in case user disappears
-  6: map<string, i64> ports
-}
-
-union RunnerCkpt {
-  1: RunnerHeader       runner_header
-  2: ProcessStatus      process_status
-  3: TaskStatus         task_status
-}
-
-struct RunnerState {
-  1: RunnerHeader header
-  2: list<TaskStatus> statuses
-  3: map<string, list<ProcessStatus>> processes
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/admin/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/admin/BUILD b/src/test/python/apache/aurora/admin/BUILD
index 101aaa0..3a21680 100644
--- a/src/test/python/apache/aurora/admin/BUILD
+++ b/src/test/python/apache/aurora/admin/BUILD
@@ -28,7 +28,7 @@ python_tests(name = 'host_maintenance',
     'src/main/python/apache/aurora/client:api',
     'src/main/python/apache/aurora/common:cluster',
     'src/main/python/apache/aurora/admin:host_maintenance',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ],
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/client/api/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/client/api/BUILD b/src/test/python/apache/aurora/client/api/BUILD
index f46ef69..2c0c407 100644
--- a/src/test/python/apache/aurora/client/api/BUILD
+++ b/src/test/python/apache/aurora/client/api/BUILD
@@ -35,7 +35,7 @@ python_tests(name = 'api',
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/api:api',
     'src/main/python/apache/aurora/client:config',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift'
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift'
   ],
 )
 
@@ -55,7 +55,7 @@ python_tests(name = 'job_monitor',
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/api:api',
     'src/main/python/apache/aurora/client/api:job_monitor',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
     'src/test/python/apache/aurora/client:fake_scheduler_proxy',
   ],
 )
@@ -65,7 +65,7 @@ python_tests(name = 'instance_watcher',
   dependencies = [
     '3rdparty/python:mox',
     'src/main/python/apache/aurora/client/api:instance_watcher',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -81,7 +81,7 @@ python_tests(name = 'quota_check',
   dependencies = [
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/api:quota_check',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -91,7 +91,7 @@ python_tests(name = 'restarter',
     '3rdparty/python:mox',
     'src/main/python/apache/aurora/client/api:restarter',
     'src/main/python/apache/aurora/common:aurora_job_key',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
     'src/test/python/apache/aurora/client:fake_scheduler_proxy',
   ],
 )
@@ -102,7 +102,7 @@ python_tests(name = 'scheduler_client',
     '3rdparty/python:mock',
     '3rdparty/python:mox',
     'src/main/python/apache/aurora/client/api:scheduler_client',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -111,7 +111,7 @@ python_tests(name = 'sla',
   dependencies = [
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/api:sla',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -121,7 +121,7 @@ python_tests(name = 'task_util',
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/api:scheduler_client',
     'src/main/python/apache/aurora/client/api:task_util',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -131,7 +131,7 @@ python_tests(name = 'updater',
     '3rdparty/python:mox',
     'src/main/python/apache/aurora/common:aurora_job_key',
     'src/main/python/apache/aurora/client/api:updater',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
     'src/test/python/apache/aurora/client:fake_scheduler_proxy',
   ]
 )
@@ -140,6 +140,6 @@ python_tests(name = 'updater_util',
   sources = ['test_updater_util.py'],
   dependencies = [
     'src/main/python/apache/aurora/client/api:api',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift'
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift'
   ],
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/client/commands/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/client/commands/BUILD b/src/test/python/apache/aurora/client/commands/BUILD
index 000eafa..86ab65e 100644
--- a/src/test/python/apache/aurora/client/commands/BUILD
+++ b/src/test/python/apache/aurora/client/commands/BUILD
@@ -41,7 +41,7 @@ python_tests(
     '3rdparty/python:mock',
     '3rdparty/python:twitter.common.contextutil',
     'src/main/python/apache/aurora/client/commands:core',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ])
 
 python_tests(
@@ -52,7 +52,7 @@ python_tests(
     '3rdparty/python:mock',
     '3rdparty/python:twitter.common.contextutil',
     'src/main/python/apache/aurora/client/commands:core',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ])
 
 python_tests(
@@ -66,7 +66,7 @@ python_tests(
     '3rdparty/python:mock',
     '3rdparty/python:twitter.common.contextutil',
     'src/main/python/apache/aurora/client/commands:admin',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ])
 
 python_tests(
@@ -79,7 +79,7 @@ python_tests(
     '3rdparty/python:mock',
     '3rdparty/python:twitter.common.contextutil',
     'src/main/python/apache/aurora/client/commands:ssh',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ])
 
 python_tests(
@@ -92,7 +92,7 @@ python_tests(
     '3rdparty/python:mock',
     '3rdparty/python:twitter.common.contextutil',
     'src/main/python/apache/aurora/client/commands:run',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ])
 
 python_tests(
@@ -112,6 +112,6 @@ python_library(
   dependencies = [
     '3rdparty/python:mock',
     'src/main/python/apache/aurora/client/commands:core',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/common/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/common/BUILD b/src/test/python/apache/aurora/common/BUILD
index 3933c46..afc0659 100644
--- a/src/test/python/apache/aurora/common/BUILD
+++ b/src/test/python/apache/aurora/common/BUILD
@@ -82,7 +82,7 @@ python_tests(
   name = 'test_transport',
   sources = ['test_transport.py'],
   dependencies = [
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
     'src/main/python/apache/aurora/common:transport',
     '3rdparty/python:mock',
   ]

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/config/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/config/BUILD b/src/test/python/apache/aurora/config/BUILD
index 551595e..c85e998 100644
--- a/src/test/python/apache/aurora/config/BUILD
+++ b/src/test/python/apache/aurora/config/BUILD
@@ -52,6 +52,6 @@ python_tests(name = 'test_thrift',
   sources = ['test_thrift.py'],
   dependencies = [
     'src/main/python/apache/aurora/config',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift-test',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift-test',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/executor/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/BUILD b/src/test/python/apache/aurora/executor/BUILD
index 23a93fd..3095f2a 100644
--- a/src/test/python/apache/aurora/executor/BUILD
+++ b/src/test/python/apache/aurora/executor/BUILD
@@ -55,9 +55,9 @@ python_tests(name = 'gc_executor',
     'src/main/python/apache/thermos/common:path',
     'src/main/python/apache/thermos/config',
     'src/main/python/apache/thermos/core:runner',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
     'src/main/python/apache/aurora/executor:gc_executor',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ],
 )
 
@@ -87,7 +87,7 @@ python_tests(name = 'thermos_executor',
     'src/main/python/apache/aurora/executor/common:task_runner',
     'src/main/python/apache/aurora/executor:aurora_executor',
     'src/main/python/apache/aurora/executor:thermos_task_runner',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/test/python/apache/aurora/executor/common/BUILD
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/BUILD b/src/test/python/apache/aurora/executor/common/BUILD
index 318e66d..4fa80b8 100644
--- a/src/test/python/apache/aurora/executor/common/BUILD
+++ b/src/test/python/apache/aurora/executor/common/BUILD
@@ -29,7 +29,7 @@ python_library(
   sources = ['fixtures.py'],
   dependencies = [
     'src/main/python/apache/aurora/config/schema',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ],
 )
 
@@ -65,7 +65,7 @@ python_tests(
     'src/main/python/apache/aurora/common:http_signaler',
     'src/main/python/apache/aurora/executor/common:health_checker',
     'src/main/python/apache/aurora/executor/common:sandbox',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -94,7 +94,7 @@ python_tests(
   dependencies = [
     ':fixtures',
     'src/main/python/apache/aurora/executor/common:task_info',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 


[3/3] incubator-aurora git commit: Extract thrift into an API subproject.

Posted by ke...@apache.org.
Extract thrift into an API subproject.

Testing Done:
./gradlew -Pq build
./pants src/test/python:all

Bugs closed: AURORA-925

Reviewed at https://reviews.apache.org/r/28361/


Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/91b8d193
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/91b8d193
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/91b8d193

Branch: refs/heads/master
Commit: 91b8d19342b3e2cc16f814a0d51a939111ecc5c9
Parents: 5e80581
Author: Kevin Sweeney <ke...@apache.org>
Authored: Tue Nov 25 14:25:08 2014 -0800
Committer: Kevin Sweeney <ke...@apache.org>
Committed: Tue Nov 25 14:25:08 2014 -0800

----------------------------------------------------------------------
 .gitignore                                      |    3 +
 BUILD                                           |    2 +
 api/src/main/thrift/org/apache/aurora/gen/BUILD |   52 +
 .../thrift/org/apache/aurora/gen/api.thrift     | 1117 ++++++++++++++++++
 .../org/apache/aurora/gen/internal_rpc.thrift   |   28 +
 .../thrift/org/apache/aurora/gen/storage.thrift |  250 ++++
 .../thrift/org/apache/aurora/gen/test.thrift    |  259 ++++
 api/src/main/thrift/org/apache/thermos/BUILD    |   25 +
 .../org/apache/thermos/thermos_internal.thrift  |   99 ++
 build-support/python/make-pycharm-virtualenv    |    4 +-
 build-support/release/make-python-sdists        |    4 +-
 build-support/thrift/thriftw                    |   40 +
 build.gradle                                    |  411 +++----
 .../apache/aurora/CoverageReportCheck.groovy    |  126 --
 .../aurora/build/CoverageReportCheck.groovy     |  128 ++
 .../aurora/build/ThriftEntitiesPlugin.groovy    |  113 ++
 .../org/apache/aurora/build/ThriftPlugin.groovy |  127 ++
 gradle/wrapper/gradle-wrapper.properties        |    4 +-
 settings.gradle                                 |   16 +-
 .../scheduler/http/JettyServerModule.java       |   38 +-
 .../aurora/scheduler/http/api/ApiBeta.java      |    2 +-
 src/main/python/apache/aurora/admin/BUILD       |    2 +-
 src/main/python/apache/aurora/client/BUILD      |    4 +-
 src/main/python/apache/aurora/client/api/BUILD  |   20 +-
 src/main/python/apache/aurora/client/cli/BUILD  |    2 +-
 .../python/apache/aurora/client/commands/BUILD  |    4 +-
 .../python/apache/aurora/client/hooks/BUILD     |    2 +-
 src/main/python/apache/aurora/common/BUILD      |    4 +-
 src/main/python/apache/aurora/common/auth/BUILD |    2 +-
 src/main/python/apache/aurora/config/BUILD      |    2 +-
 .../python/apache/aurora/config/schema/BUILD    |    2 +-
 src/main/python/apache/aurora/executor/BUILD    |    4 +-
 .../python/apache/aurora/executor/common/BUILD  |    2 +-
 .../aurora/tools/java/thrift_wrapper_codegen.py |   11 +-
 src/main/python/apache/thermos/bin/BUILD        |    4 +-
 src/main/python/apache/thermos/common/BUILD     |    4 +-
 src/main/python/apache/thermos/core/BUILD       |   12 +-
 src/main/python/apache/thermos/monitoring/BUILD |    2 +-
 src/main/python/apache/thermos/observer/BUILD   |    2 +-
 src/main/python/apache/thermos/testing/BUILD    |    2 +-
 .../scheduler/assets/scheduler/index.html       |    4 +-
 src/main/thrift/org/apache/aurora/gen/BUILD     |   52 -
 .../thrift/org/apache/aurora/gen/api.thrift     | 1117 ------------------
 .../org/apache/aurora/gen/internal_rpc.thrift   |   28 -
 .../thrift/org/apache/aurora/gen/storage.thrift |  250 ----
 .../thrift/org/apache/aurora/gen/test.thrift    |  259 ----
 src/main/thrift/org/apache/thermos/BUILD        |   25 -
 .../org/apache/thermos/thermos_internal.thrift  |   99 --
 src/test/python/apache/aurora/admin/BUILD       |    2 +-
 src/test/python/apache/aurora/client/api/BUILD  |   20 +-
 .../python/apache/aurora/client/commands/BUILD  |   12 +-
 src/test/python/apache/aurora/common/BUILD      |    2 +-
 src/test/python/apache/aurora/config/BUILD      |    2 +-
 src/test/python/apache/aurora/executor/BUILD    |    6 +-
 .../python/apache/aurora/executor/common/BUILD  |    6 +-
 55 files changed, 2538 insertions(+), 2281 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index ec072d2..8684097 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,12 +9,15 @@
 /.idea/*
 /.pants.*
 /.vagrant/*
+/api/dist/*
+/atlassian-ide-plugin.xml
 /build/*
 /build-support/*.pex
 /build-support/*.venv
 /build-support/python/*.venv
 /build-support/virtualenv-*
 /buildSrc/build/*
+/buildSrc/dist/*
 /dist/*
 /gradle-app.setting
 /out/*

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/BUILD
----------------------------------------------------------------------
diff --git a/BUILD b/BUILD
index b6d7ce9..992f675 100644
--- a/BUILD
+++ b/BUILD
@@ -12,6 +12,8 @@
 # limitations under the License.
 #
 
+source_root('api/src/main/thrift', python_library, python_thrift_library)
+
 source_root('src/main/python', page, python_binary, python_library, resources)
 source_root('src/main/thrift', python_library, python_thrift_library)
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/aurora/gen/BUILD
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/aurora/gen/BUILD b/api/src/main/thrift/org/apache/aurora/gen/BUILD
new file mode 100644
index 0000000..fe3f83b
--- /dev/null
+++ b/api/src/main/thrift/org/apache/aurora/gen/BUILD
@@ -0,0 +1,52 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+
+TEST_DATA = globs('*test.thrift')
+
+python_thrift_library(
+  name = 'py-thrift',
+  sources = [
+    'api.thrift',
+    'internal_rpc.thrift',
+  ],
+)
+
+python_thrift_library(
+  name = 'py-thrift-test',
+  sources = TEST_DATA,
+)
+
+python_thrift_library(
+  name = 'py-thrift-storage',
+  sources = ['storage.thrift'],
+  dependencies = [
+    ':py-thrift',
+  ],
+)
+
+python_library(
+  name = 'py-thrift-packaged',
+  dependencies = [
+    ':py-thrift',
+    ':py-thrift-test',
+    ':py-thrift-storage',
+  ],
+  provides = setup_py(
+    name = 'apache.gen.aurora',
+    version = open(os.path.join(get_buildroot(), '.auroraversion')).read().strip().upper(),
+    description = 'Autogenerated Aurora thrift schemas.',
+  )
+)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/aurora/gen/api.thrift
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/aurora/gen/api.thrift b/api/src/main/thrift/org/apache/aurora/gen/api.thrift
new file mode 100644
index 0000000..b91fca9
--- /dev/null
+++ b/api/src/main/thrift/org/apache/aurora/gen/api.thrift
@@ -0,0 +1,1117 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace java org.apache.aurora.gen
+namespace py gen.apache.aurora.api
+
+// Thrift interface definition for the aurora scheduler.
+
+/*
+ * TODO(wfarner): It would be nice if we could put some HTML tags here, regex doesn't handle it though.
+ * The result of an API operation.  A result may only be specified when this is OK.
+ */
+enum ResponseCode {
+  INVALID_REQUEST = 0,
+  OK              = 1,
+  ERROR           = 2,
+  WARNING         = 3,
+  AUTH_FAILED     = 4,
+  /** Raised when a Lock-protected operation failed due to lock validation. */
+  LOCK_ERROR      = 5,
+  /** Raised when a scheduler is transiently unavailable and later retry is recommended. */
+  ERROR_TRANSIENT = 6
+}
+
+const i32 THRIFT_API_VERSION = 3
+
+struct APIVersion {
+  1: required i32 major
+}
+
+// Scheduler Thrift API Version. Increment this when breaking backwards compatibility.
+const APIVersion CURRENT_API_VERSION = {'major': THRIFT_API_VERSION}
+
+// Aurora executor framework name.
+const string AURORA_EXECUTOR_NAME = 'AuroraExecutor'
+
+// TODO(maxim): Remove in 0.7.0. (AURORA-749)
+struct Identity {
+  1: string role
+  2: string user
+}
+
+struct SessionKey {
+  /**
+   * The name of the authentication mechanism, which instructs the server how to interpret the data
+   * field.
+   */
+  4: optional string mechanism
+  /** A blob of data that the server may use for authentication. */
+  5: optional binary data
+}
+
+struct ResourceAggregate {
+  /** Number of CPU cores allotted. */
+  1: double numCpus
+  /** Megabytes of RAM allotted. */
+  2: i64 ramMb
+  /** Megabytes of disk space allotted. */
+  3: i64 diskMb
+}
+
+/** A single host attribute. */
+struct Attribute {
+  1: string name
+  2: set<string> values
+}
+
+enum MaintenanceMode {
+  NONE      = 1,
+  SCHEDULED = 2,
+  DRAINING  = 3,
+  DRAINED   = 4
+}
+
+/** The attributes assigned to a host. */
+struct HostAttributes {
+  1: string          host
+  2: set<Attribute>  attributes
+  3: optional MaintenanceMode mode
+  4: optional string slaveId
+}
+
+/**
+ * A constraint that specifies an explicit set of values, at least one of which must be present
+ * on a host for a task to be scheduled there.
+ */
+struct ValueConstraint {
+  /** If true, treat this as a 'not' - to avoid specific values. */
+  1: bool negated
+  2: set<string> values
+}
+
+/**
+ * A constraint the specifies the maximum number of active tasks on a host with a matching
+ * attribute that may be scheduled simultaneously.
+ */
+struct LimitConstraint {
+  1: i32 limit
+}
+
+/** Types of constraints that may be applied to a task. */
+union TaskConstraint {
+  1: ValueConstraint value
+  2: LimitConstraint limit
+}
+
+/** A constraint that defines whether a task may be scheduled on a host. */
+struct Constraint {
+  /** Mesos slave attribute that the constraint is matched against. */
+  1: string name
+  2: TaskConstraint constraint
+}
+
+struct Package {
+  1: string role
+  2: string name
+  3: i32 version
+}
+
+/** Arbitrary key-value metadata to be included into TaskConfig. */
+struct Metadata {
+  1: string key
+  2: string value
+}
+
+/** A unique identifier for a Job. */
+struct JobKey {
+  /** User role (Unix service account), for example "mesos" */
+  1: string role
+  /** Environment, for example "devel" */
+  2: string environment
+  /** Name, for example "labrat" */
+  3: string name
+}
+
+/** A unique lock key. */
+union LockKey {
+  1: JobKey job
+}
+
+/** A generic lock struct to facilitate context specific resource/operation serialization. */
+struct Lock {
+  /** ID of the lock - unique per storage */
+  1: LockKey key
+  /** UUID - facilitating soft lock authorization */
+  2: string token
+  /** Lock creator */
+  3: string user
+  /** Lock creation timestamp in milliseconds */
+  4: i64 timestampMs
+  /** Optional message to record with the lock */
+  5: optional string message
+}
+
+/** Defines the required lock validation level. */
+enum LockValidation {
+  /** The lock must be valid in order to be released. */
+  CHECKED   = 0
+  /** The lock will be released without validation (aka "force release"). */
+  UNCHECKED = 1
+}
+
+/** A unique identifier for the active task within a job. */
+struct InstanceKey {
+  /** Key identifying the job. */
+  1: JobKey jobKey
+  /** Unique instance ID for the active task in a job. */
+  2: i32 instanceId
+}
+
+struct ExecutorConfig {
+  /** Name identifying the Executor. */
+  1: string name
+  /** Executor configuration data. */
+  2: string data
+}
+
+/** Description of the tasks contained within a job. */
+struct TaskConfig {
+ /** Job task belongs to. */
+ 28: JobKey job
+ // TODO(maxim): Remove in 0.7.0. (AURORA-749)
+ /** contains the role component of JobKey */
+ 17: Identity owner
+ // TODO(maxim): Remove in 0.7.0. (AURORA-749)
+ /** contains the environment component of JobKey */
+ 26: string environment
+ // TODO(maxim): Remove in 0.7.0. (AURORA-749)
+ /** contains the name component of JobKey */
+  3: string jobName
+  7: bool isService
+  8: double numCpus
+  9: i64 ramMb
+ 10: i64 diskMb
+ 11: i32 priority
+ 13: i32 maxTaskFailures
+ /** Whether this is a production task, which can preempt. */
+ 18: optional bool production
+
+ 20: set<Constraint> constraints
+ /** a list of named ports this task requests */
+ 21: set<string> requestedPorts
+
+ /**
+  * Custom links to include when displaying this task on the scheduler dashboard. Keys are anchor
+  * text, values are URLs. Wildcards are supported for dynamic link crafting based on host, ports,
+  * instance, etc.
+  */
+ 22: optional map<string, string> taskLinks
+ 23: optional string contactEmail
+ /** Executor configuration */
+ 25: optional ExecutorConfig executorConfig
+ /** Used to display additional details in the UI. */
+ 27: optional set<Metadata> metadata
+}
+
+/** Defines the policy for launching a new cron job when one is already running. */
+enum CronCollisionPolicy {
+  /** Kills the existing job with the colliding name, and runs the new cron job. */
+  KILL_EXISTING = 0,
+  /** Cancels execution of the new job, leaving the running job in tact. */
+  CANCEL_NEW    = 1,
+  /**
+   * DEPRECATED. For existing jobs, treated the same as CANCEL_NEW.
+   * createJob will reject jobs with this policy.
+   */
+  RUN_OVERLAP   = 2
+}
+
+/**
+ * Description of an Aurora job. One task will be scheduled for each instance within the job.
+ */
+struct JobConfiguration {
+  /**
+   * Key for this job. If not specified name, owner.role, and a reasonable default environment are
+   * used to construct it server-side.
+   */
+  9: JobKey key
+  // TODO(maxim): Remove in 0.7.0. (AURORA-749)
+  /** Owner of this job. */
+  7: Identity owner
+  /**
+   * If present, the job will be handled as a cron job with this crontab-syntax schedule.
+   */
+  4: string cronSchedule
+  /** Collision policy to use when handling overlapping cron runs.  Default is KILL_EXISTING. */
+  5: CronCollisionPolicy cronCollisionPolicy
+  /** Task configuration for this job. */
+  6: TaskConfig taskConfig
+  /**
+   * The number of instances in the job. Generated instance IDs for tasks will be in the range
+   * [0, instances).
+   */
+  8: i32 instanceCount
+}
+
+struct JobStats {
+  /** Number of tasks in active state for this job. */
+  1: i32 activeTaskCount
+  /** Number of tasks in finished state for this job. */
+  2: i32 finishedTaskCount
+  /** Number of failed tasks for this job. */
+  3: i32 failedTaskCount
+  /** Number of tasks in pending state for this job. */
+  4: i32 pendingTaskCount
+}
+
+struct JobSummary {
+  1: JobConfiguration job
+  2: JobStats stats
+  /** Timestamp of next cron run in ms since epoch, for a cron job */
+  3: optional i64 nextCronRunMs
+}
+
+/** A request to add the following instances to an existing job. Used by addInstances. */
+struct AddInstancesConfig {
+  1: JobKey key
+  2: TaskConfig taskConfig
+  3: set<i32> instanceIds
+}
+
+/** Closed range of integers. */
+struct Range {
+  1: i32 first
+  2: i32 last
+}
+
+struct ConfigGroup {
+  1: TaskConfig config
+  2: set<i32> instanceIds   // TODO(maxim): change it to use list<Range> instead.
+}
+
+struct ConfigSummary {
+  1: JobKey key
+  2: set<ConfigGroup> groups
+}
+
+struct PopulateJobResult {
+  // TODO(maxim): Remove populated field in 0.7.0. (AURORA-691)
+  1: set<TaskConfig> populatedDEPRECATED
+  2: TaskConfig taskConfig
+}
+
+struct GetQuotaResult {
+  /** Total allocated resource quota. */
+  1: ResourceAggregate quota
+  /** Resources consumed by production jobs. */
+  2: optional ResourceAggregate prodConsumption
+  /** Resources consumed by non-production jobs. */
+  3: optional ResourceAggregate nonProdConsumption
+}
+
+/** Wraps return results for the acquireLock API. */
+struct AcquireLockResult {
+  /** Acquired Lock instance. */
+  1: Lock lock
+}
+
+/** States that a task may be in. */
+enum ScheduleStatus {
+  // TODO(maxim): This state does not add much value. Consider dropping it completely.
+  /* Initial state for a task.  A task will remain in this state until it has been persisted. */
+  INIT             = 11,
+  /** The task will be rescheduled, but is being throttled for restarting too frequently. */
+  THROTTLED        = 16,
+  /** Task is awaiting assignment to a slave. */
+  PENDING          = 0,
+  /** Task has been assigned to a slave. */
+  ASSIGNED         = 9,
+  /** Slave has acknowledged receipt of task and is bootstrapping the task. */
+  STARTING         = 1,
+  /** The task is running on the slave. */
+  RUNNING          = 2,
+  /** The task terminated with an exit code of zero. */
+  FINISHED         = 3,
+  /** The task is being preempted by another task. */
+  PREEMPTING       = 13,
+  /** The task is being restarted in response to a user request. */
+  RESTARTING       = 12,
+  /** The task is being restarted in response to a host maintenance request. */
+  DRAINING         = 17,
+  /** The task terminated with a non-zero exit code. */
+  FAILED           = 4,
+  /** Execution of the task was terminated by the system. */
+  KILLED           = 5,
+  /** The task is being forcibly killed. */
+  KILLING          = 6,
+  /** A fault in the task environment has caused the system to believe the task no longer exists.
+   * This can happen, for example, when a slave process disappears.
+   */
+  LOST             = 7,
+  // TODO(maxim): Remove SANDBOX_DELETED in 0.7.0. (AURORA-832)
+  /** The task sandbox has been deleted by the executor. */
+  SANDBOX_DELETED  = 10
+}
+
+// States that a task may be in while still considered active.
+const set<ScheduleStatus> ACTIVE_STATES = [ScheduleStatus.ASSIGNED,
+                                           ScheduleStatus.DRAINING,
+                                           ScheduleStatus.KILLING,
+                                           ScheduleStatus.PENDING,
+                                           ScheduleStatus.PREEMPTING,
+                                           ScheduleStatus.RESTARTING
+                                           ScheduleStatus.RUNNING,
+                                           ScheduleStatus.STARTING,
+                                           ScheduleStatus.THROTTLED]
+
+// States that a task may be in while associated with a slave machine and non-terminal.
+const set<ScheduleStatus> SLAVE_ASSIGNED_STATES = [ScheduleStatus.ASSIGNED,
+                                                   ScheduleStatus.DRAINING,
+                                                   ScheduleStatus.KILLING,
+                                                   ScheduleStatus.PREEMPTING,
+                                                   ScheduleStatus.RESTARTING,
+                                                   ScheduleStatus.RUNNING,
+                                                   ScheduleStatus.STARTING]
+
+// States that a task may be in while in an active sandbox.
+const set<ScheduleStatus> LIVE_STATES = [ScheduleStatus.KILLING,
+                                         ScheduleStatus.PREEMPTING,
+                                         ScheduleStatus.RESTARTING,
+                                         ScheduleStatus.DRAINING,
+                                         ScheduleStatus.RUNNING]
+
+// States a completed task may be in.
+const set<ScheduleStatus> TERMINAL_STATES = [ScheduleStatus.FAILED,
+                                             ScheduleStatus.FINISHED,
+                                             ScheduleStatus.KILLED,
+                                             ScheduleStatus.LOST,
+                                             ScheduleStatus.SANDBOX_DELETED]
+
+// Regular expressions for matching valid identifiers for job path components. All expressions
+// below should accept and reject the same set of inputs.
+const string GOOD_IDENTIFIER_PATTERN = "^[\\w\\-\\.]+$"
+// JVM: Use with java.util.regex.Pattern#compile
+const string GOOD_IDENTIFIER_PATTERN_JVM = GOOD_IDENTIFIER_PATTERN
+// Python: Use with re.compile
+const string GOOD_IDENTIFIER_PATTERN_PYTHON = GOOD_IDENTIFIER_PATTERN
+
+/** Event marking a state transition within a task's lifecycle. */
+struct TaskEvent {
+  /** Epoch timestamp in milliseconds. */
+  1: i64 timestamp
+  /** New status of the task. */
+  2: ScheduleStatus status
+  /** Audit message that explains why a transition occurred. */
+  3: optional string message
+  /** Hostname of the scheduler machine that performed the event. */
+  4: optional string scheduler
+}
+
+/** A task assignment that is provided to an executor. */
+struct AssignedTask {
+  /** The mesos task ID for this task.  Guaranteed to be globally unique */
+  1: string taskId
+
+  /**
+   * The mesos slave ID that this task has been assigned to.
+   * This will not be populated for a PENDING task.
+   */
+  2: string slaveId
+
+  /**
+   * The name of the machine that this task has been assigned to.
+   * This will not be populated for a PENDING task.
+   */
+  3: string slaveHost
+
+  /** Information about how to run this task. */
+  4: TaskConfig task
+  /** Ports reserved on the machine while this task is running. */
+  5: map<string, i32> assignedPorts
+
+  /**
+   * The instance ID assigned to this task. Instance IDs must be unique and contiguous within a
+   * job, and will be in the range [0, N-1] (inclusive) for a job that has N instances.
+   */
+  6: i32 instanceId
+}
+
+/** A task that has been scheduled. */
+struct ScheduledTask {
+  /** The task that was scheduled. */
+  1: AssignedTask assignedTask
+  /** The current status of this task. */
+  2: ScheduleStatus status
+  /**
+   * The number of failures that this task has accumulated over the multi-generational history of
+   * this task.
+   */
+  3: i32 failureCount
+  /** State change history for this task. */
+  4: list<TaskEvent> taskEvents
+  /**
+   * The task ID of the previous generation of this task.  When a task is automatically rescheduled,
+   * a copy of the task is created and ancestor ID of the previous task's task ID.
+   */
+  5: string ancestorId
+}
+
+struct ScheduleStatusResult {
+  1: list<ScheduledTask> tasks
+}
+
+struct GetJobsResult {
+  1: set<JobConfiguration> configs
+}
+
+/**
+ * Contains a set of restrictions on matching tasks where all restrictions must be met
+ * (terms are AND'ed together).
+ */
+struct TaskQuery {
+  // TODO(maxim): Remove in 0.7.0. (AURORA-749)
+  8: Identity owner
+  14: string role
+  9: string environment
+  2: string jobName
+  4: set<string> taskIds
+  5: set<ScheduleStatus> statuses
+  7: set<i32> instanceIds
+  10: set<string> slaveHosts
+  11: set<JobKey> jobKeys
+  12: i32 offset
+  13: i32 limit
+}
+
+struct HostStatus {
+  1: string host
+  2: MaintenanceMode mode
+}
+
+struct RoleSummary {
+  1: string role
+  2: i32 jobCount
+  3: i32 cronJobCount
+}
+
+struct Hosts {
+  1: set<string> hostNames
+}
+
+struct PendingReason {
+  1: string taskId
+  2: string reason
+}
+
+/** States that a job update may be in. */
+enum JobUpdateStatus {
+  /** Update is in progress. */
+  ROLLING_FORWARD = 0,
+
+  /** Update has failed and is being rolled back. */
+  ROLLING_BACK = 1,
+
+  /** Update has been paused while in progress. */
+  ROLL_FORWARD_PAUSED = 2,
+
+  /** Update has been paused during rollback. */
+  ROLL_BACK_PAUSED = 3,
+
+  /** Update has completed successfully. */
+  ROLLED_FORWARD = 4,
+
+  /** Update has failed and rolled back. */
+  ROLLED_BACK = 5,
+
+  /** Update was aborted. */
+  ABORTED = 6,
+
+  /** Unknown error during update. */
+  ERROR = 7
+
+  /**
+   * Update failed to complete.
+   * This can happen if failure thresholds are met while rolling forward, but rollback is disabled,
+   * or if failure thresholds are met when rolling back.
+   */
+  FAILED = 8
+}
+
+/** States the job update can be in while still considered active. */
+const set<JobUpdateStatus> ACTIVE_JOB_UPDATE_STATES = [JobUpdateStatus.ROLLING_FORWARD,
+                                                       JobUpdateStatus.ROLLING_BACK,
+                                                       JobUpdateStatus.ROLL_FORWARD_PAUSED,
+                                                       JobUpdateStatus.ROLL_BACK_PAUSED]
+
+/** Job update actions that can be applied to job instances. */
+enum JobUpdateAction {
+  /**
+   * An instance was moved to the target state successfully, and declared healthy if the desired
+   * state did not involve deleting the instance.
+   */
+  INSTANCE_UPDATED = 1,
+
+  /**
+   * An instance was rolled back because the job update did not succeed.  The instance was reverted
+   * to the original state prior to the job update, which means that the instance was removed if
+   * the update added instances to the job.
+   */
+  INSTANCE_ROLLED_BACK = 2,
+
+  /**
+   * An instance is being moved from the original state to the desired state.
+   */
+  INSTANCE_UPDATING = 3,
+
+  /**
+   * An instance is being moved from the desired state back to the original state, because the job
+   * update failed.
+   */
+  INSTANCE_ROLLING_BACK = 4,
+
+  /** An instance update was attempted but failed and was not rolled back. */
+  INSTANCE_UPDATE_FAILED = 5,
+
+  /** An instance rollback was attempted but failed. */
+  INSTANCE_ROLLBACK_FAILED = 6
+}
+
+/** Status of the coordinated update. Intended as a response to pulseJobUpdate RPC. */
+enum JobUpdatePulseStatus {
+  /**
+   *  Update is active (ACK).
+   */
+  OK = 1,
+
+  /**
+   * Update is paused and will not progress unless explicitly resumed (NACK).
+   */
+  PAUSED = 2,
+
+  /**
+   * Update has reached terminal state.
+   */
+  FINISHED = 3
+}
+
+/** Job update thresholds and limits. */
+struct JobUpdateSettings {
+  /** Max number of instances being updated at any given moment. */
+  1: i32 updateGroupSize
+
+  /** Max number of instance failures to tolerate before marking instance as FAILED. */
+  2: i32 maxPerInstanceFailures
+
+  /** Max number of FAILED instances to tolerate before terminating the update. */
+  3: i32 maxFailedInstances
+
+  /** Max time to wait until an instance reaches RUNNING state. */
+  4: i32 maxWaitToInstanceRunningMs
+
+  /** Min time to watch a RUNNING instance. */
+  5: i32 minWaitInInstanceRunningMs
+
+  /** If true, enables failed update rollback. */
+  6: bool rollbackOnFailure
+
+  /** Instance IDs to act on. All instances will be affected if this is not set. */
+  7: set<Range> updateOnlyTheseInstances
+
+  /**
+   * If true, use updateGroupSize as strict batching boundaries, and avoid proceeding to another
+   * batch until the preceding batch finishes updating.
+   */
+  8: bool waitForBatchCompletion
+
+ /**
+  * If set, requires external calls to pulseJobUpdate RPC within the specified rate for the
+  * update to make progress. If no pulses received within specified interval the update will
+  * block. A blocked update is unable to continue but retains its current status. It may only get
+  * unblocked by a fresh pulseJobUpdate call.
+  */
+  9: i32 blockIfNoPulsesAfterMs
+}
+
+/** Event marking a state transition in job update lifecycle. */
+struct JobUpdateEvent {
+  /** Update status. */
+  1: JobUpdateStatus status
+
+  /** Epoch timestamp in milliseconds. */
+  2: i64 timestampMs
+
+  /** User who performed this event (if user-initiated). */
+  3: optional string user
+}
+
+/** Event marking a state transition in job instance update lifecycle. */
+struct JobInstanceUpdateEvent {
+  /** Job instance ID. */
+  1: i32 instanceId
+
+  /** Epoch timestamp in milliseconds. */
+  2: i64 timestampMs
+
+  /** Job update action taken on the instance. */
+  3: JobUpdateAction action
+}
+
+/** Maps instance IDs to TaskConfigs it. */
+struct InstanceTaskConfig {
+  /** A TaskConfig associated with instances. */
+  1: TaskConfig task
+
+  /** Instances associated with the TaskConfig. */
+  2: set<Range> instances
+}
+
+/** Current job update state including status and created/modified timestamps. */
+struct JobUpdateState {
+  /** Current status of the update. */
+  1: JobUpdateStatus status
+
+  /** Created timestamp in milliseconds. */
+  2: i64 createdTimestampMs
+
+  /** Last modified timestamp in milliseconds. */
+  3: i64 lastModifiedTimestampMs
+}
+
+/** Summary of the job update including job key, user and current state. */
+struct JobUpdateSummary {
+  /** Update ID. */
+  1: string updateId
+
+  /** Job key. */
+  2: JobKey jobKey
+
+  /** User initiated an update. */
+  3: string user
+
+  /** Current job update state. */
+  4: JobUpdateState state
+}
+
+/** Update configuration and setting details. */
+struct JobUpdateInstructions {
+  /** Actual InstanceId -> TaskConfig mapping when the update was requested. */
+  1: set<InstanceTaskConfig> initialState
+
+  /** Desired configuration when the update completes. */
+  2: InstanceTaskConfig desiredState
+
+  /** Update specific settings. */
+  3: JobUpdateSettings settings
+}
+
+/** Full definition of the job update. */
+struct JobUpdate {
+  /** Update summary. */
+  1: JobUpdateSummary summary
+
+  /** Update configuration. */
+  2: JobUpdateInstructions instructions
+}
+
+struct JobUpdateDetails {
+  /** Update definition. */
+  1: JobUpdate update
+
+  /** History for this update. */
+  2: list<JobUpdateEvent> updateEvents
+
+  /** History for the individual instances updated. */
+  3: list<JobInstanceUpdateEvent> instanceEvents
+}
+
+/** A request to update the following instances of an existing job. Used by startUpdate. */
+struct JobUpdateRequest {
+  /** Desired TaskConfig to apply. */
+  1: TaskConfig taskConfig
+
+  /** Desired number of instances of the task config. */
+  2: i32 instanceCount
+
+  /** Update settings and limits. */
+  3: JobUpdateSettings settings
+}
+
+/**
+ * Contains a set of restrictions on matching job updates where all restrictions must be met
+ * (terms are AND'ed together).
+ */
+struct JobUpdateQuery {
+  /** Update ID. */
+  1: string updateId
+
+  /** Job role. */
+  2: string role
+
+  /** Job key. */
+  3: JobKey jobKey
+
+  /** User who created the update. */
+  4: string user
+
+  /** Set of update statuses. */
+  5: set<JobUpdateStatus> updateStatuses
+
+  /** Offset to serve data from. Used by pagination. */
+  6: i32 offset
+
+  /** Number or records to serve. Used by pagination. */
+  7: i32 limit
+}
+
+struct ListBackupsResult {
+  1: set<string> backups
+}
+
+struct StartMaintenanceResult {
+  1: set<HostStatus> statuses
+}
+
+struct DrainHostsResult {
+  1: set<HostStatus> statuses
+}
+
+struct QueryRecoveryResult {
+  1: set<ScheduledTask> tasks
+}
+
+struct MaintenanceStatusResult {
+  1: set<HostStatus> statuses
+}
+
+struct EndMaintenanceResult {
+  1: set<HostStatus> statuses
+}
+
+struct RoleSummaryResult {
+  1: set<RoleSummary> summaries
+}
+
+struct JobSummaryResult {
+  1: set<JobSummary> summaries
+}
+
+struct GetLocksResult {
+  1: set<Lock> locks
+}
+
+struct ConfigSummaryResult {
+  1: ConfigSummary summary
+}
+
+struct GetPendingReasonResult {
+  1: set<PendingReason> reasons
+}
+
+/** Result of the startUpdate call. */
+struct StartJobUpdateResult {
+  /** Job update ID. */
+  1: string updateId
+}
+
+/** Result of the getJobUpdateSummaries call. */
+struct GetJobUpdateSummariesResult {
+  1: list<JobUpdateSummary> updateSummaries
+}
+
+/** Result of the getJobUpdateDetails call. */
+struct GetJobUpdateDetailsResult {
+  1: JobUpdateDetails details
+}
+
+/** Result of the pulseJobUpdate call. */
+struct PulseJobUpdateResult {
+  1: JobUpdatePulseStatus status
+}
+
+/** Information about the scheduler. */
+struct ServerInfo {
+  1: string clusterName
+  2: i32 thriftAPIVersion
+  /** A url prefix for job container stats. */
+  3: string statsUrlPrefix
+}
+
+union Result {
+  1: PopulateJobResult populateJobResult
+  3: ScheduleStatusResult scheduleStatusResult
+  4: GetJobsResult getJobsResult
+  5: GetQuotaResult getQuotaResult
+  6: ListBackupsResult listBackupsResult
+  7: StartMaintenanceResult startMaintenanceResult
+  8: DrainHostsResult drainHostsResult
+  9: QueryRecoveryResult queryRecoveryResult
+  10: MaintenanceStatusResult maintenanceStatusResult
+  11: EndMaintenanceResult endMaintenanceResult
+  15: APIVersion getVersionResult
+  16: AcquireLockResult acquireLockResult
+  17: RoleSummaryResult roleSummaryResult
+  18: JobSummaryResult jobSummaryResult
+  19: GetLocksResult getLocksResult
+  20: ConfigSummaryResult configSummaryResult
+  21: GetPendingReasonResult getPendingReasonResult
+  22: StartJobUpdateResult startJobUpdateResult
+  23: GetJobUpdateSummariesResult getJobUpdateSummariesResult
+  24: GetJobUpdateDetailsResult getJobUpdateDetailsResult
+  25: PulseJobUpdateResult pulseJobUpdateResult
+}
+
+struct ResponseDetail {
+  1: string message
+}
+
+struct Response {
+  1: ResponseCode responseCode
+  // TODO(wfarner): Remove the message field in 0.7.0. (AURORA-466)
+  2: optional string messageDEPRECATED
+  // TODO(wfarner): Remove version field in 0.7.0. (AURORA-467)
+  4: APIVersion DEPRECATEDversion
+  5: ServerInfo serverInfo
+  /** Payload from the invoked RPC. */
+  3: optional Result result
+  /**
+   * Messages from the server relevant to the request, such as warnings or use of deprecated
+   * features.
+   */
+  6: list<ResponseDetail> details
+}
+
+// A service that provides all the read only calls to the Aurora scheduler.
+service ReadOnlyScheduler {
+  /** Returns a summary of the jobs grouped by role. */
+  Response getRoleSummary()
+
+  /** Returns a summary of jobs, optionally only those owned by a specific role. */
+  Response getJobSummary(1: string role)
+
+  /** Fetches the status of tasks. */
+  Response getTasksStatus(1: TaskQuery query)
+
+  /**
+   * Same as getTaskStatus but without the TaskConfig.ExecutorConfig data set.
+   * This is an interim solution until we have a better way to query TaskConfigs (AURORA-541).
+   */
+  Response getTasksWithoutConfigs(1: TaskQuery query)
+
+  /** Returns user-friendly reasons (if available) for tasks retained in PENDING state. */
+  Response getPendingReason(1: TaskQuery query)
+
+  /** Fetches the configuration summary of active tasks for the specified job. */
+  Response getConfigSummary(1: JobKey job)
+
+  /**
+   * Fetches the status of jobs.
+   * ownerRole is optional, in which case all jobs are returned.
+   */
+  Response getJobs(1: string ownerRole)
+
+  /** Fetches the quota allocated for a user. */
+  Response getQuota(1: string ownerRole)
+
+  // TODO(Suman Karumuri): Delete this API once it is no longer used.
+  /**
+   * Returns the current version of the API implementation
+   * NOTE: This method is deprecated.
+   */
+  Response getVersion()
+
+  /**
+   * Populates fields in a job configuration as though it were about to be run.
+   * This can be used to diff a configuration running tasks.
+   */
+  Response populateJobConfig(1: JobConfiguration description)
+
+  /** Returns all stored context specific resource/operation locks. */
+  Response getLocks()
+
+  /** Gets job update summaries. Not implemented yet. */
+  Response getJobUpdateSummaries(1: JobUpdateQuery jobUpdateQuery)
+
+  /** Gets job update details. Not implemented yet. */
+  Response getJobUpdateDetails(1: string updateId)
+}
+
+// Due to assumptions in the client all authenticated RPCs must have a SessionKey as their
+// last argument. Note that the order in this file is what matters, and message numbers should still
+// never be reused.
+service AuroraSchedulerManager extends ReadOnlyScheduler {
+  /**
+   * Creates a new job.  The request will be denied if a job with the provided name already exists
+   * in the cluster.
+   */
+  Response createJob(1: JobConfiguration description, 3: Lock lock, 2: SessionKey session)
+
+  /**
+   * Enters a job into the cron schedule, without actually starting the job.
+   * If the job is already present in the schedule, this will update the schedule entry with the new
+   * configuration.
+   */
+  Response scheduleCronJob(1: JobConfiguration description, 3: Lock lock, 2: SessionKey session)
+
+  /**
+   * Removes a job from the cron schedule. The request will be denied if the job was not previously
+   * scheduled with scheduleCronJob.
+   */
+  Response descheduleCronJob(4: JobKey job, 3: Lock lock, 2: SessionKey session)
+
+  /**
+   * Starts a cron job immediately.  The request will be denied if the specified job does not
+   * exist for the role account, or the job is not a cron job.
+   */
+  Response startCronJob(4: JobKey job, 3: SessionKey session)
+
+  /** Restarts a batch of shards. */
+  Response restartShards(5: JobKey job, 3: set<i32> shardIds, 6: Lock lock 4: SessionKey session)
+
+  /** Initiates a kill on tasks. */
+  Response killTasks(1: TaskQuery query, 3: Lock lock, 2: SessionKey session)
+
+  /**
+   * Adds new instances specified by the AddInstancesConfig. A job represented by the JobKey must be
+   * protected by Lock.
+   */
+  Response addInstances(
+      1: AddInstancesConfig config,
+      2: Lock lock,
+      3: SessionKey session)
+
+  /**
+   * Creates and saves a new Lock instance guarding against multiple mutating operations within the
+   * context defined by LockKey.
+   */
+  Response acquireLock(1: LockKey lockKey, 2: SessionKey session)
+
+  /** Releases the lock acquired earlier in acquireLock call. */
+  Response releaseLock(1: Lock lock, 2: LockValidation validation, 3: SessionKey session)
+
+  /**
+   * Replaces the template (configuration) for the existing cron job.
+   * The cron job template (configuration) must exist for the call to succeed.
+   */
+  Response replaceCronTemplate(1: JobConfiguration config, 2: Lock lock, 3: SessionKey session)
+
+  /** Starts update of the existing service job. Not implemented yet. */
+  Response startJobUpdate(1: JobUpdateRequest request, 2: SessionKey session)
+
+  /**
+   * Pauses the update progress for the specified job. Can be resumed by resumeUpdate call.
+   * Not implemented yet.
+   */
+  Response pauseJobUpdate(1: JobKey jobKey, 2: SessionKey session)
+
+  /** Resumes progress of a previously paused job update. Not implemented yet. */
+  Response resumeJobUpdate(1: JobKey jobKey, 2: SessionKey session)
+
+  /** Permanently aborts the job update. Does not remove the update history. Not implemented yet. */
+  Response abortJobUpdate(1: JobKey jobKey, 2: SessionKey session)
+
+  /**
+   * Allows progress of the job update in case blockIfNoPulsesAfterMs is specified in
+   * JobUpdateSettings. Unblocks progress if the update was previously blocked.
+   * Responds with ResponseCode.INVALID_REQUEST in case an unknown updateId is specified.
+   */
+  Response pulseJobUpdate(1: string updateId, 2: SessionKey session)
+}
+
+struct InstanceConfigRewrite {
+  /** Key for the task to rewrite. */
+  1: InstanceKey instanceKey
+  /** The original configuration. */
+  2: TaskConfig oldTask
+  /** The rewritten configuration. */
+  3: TaskConfig rewrittenTask
+}
+
+struct JobConfigRewrite {
+  /** The original job configuration. */
+  1: JobConfiguration oldJob
+  /** The rewritten job configuration. */
+  2: JobConfiguration rewrittenJob
+}
+
+union ConfigRewrite {
+  1: JobConfigRewrite jobRewrite
+  2: InstanceConfigRewrite instanceRewrite
+}
+
+struct RewriteConfigsRequest {
+  1: list<ConfigRewrite> rewriteCommands
+}
+
+// It would be great to compose these services rather than extend, but that won't be possible until
+// https://issues.apache.org/jira/browse/THRIFT-66 is resolved.
+service AuroraAdmin extends AuroraSchedulerManager {
+  /** Assign quota to a user.  This will overwrite any pre-existing quota for the user. */
+  Response setQuota(1: string ownerRole, 2: ResourceAggregate quota, 3: SessionKey session)
+
+  /**
+   * Forces a task into a specific state.  This does not guarantee the task will enter the given
+   * state, as the task must still transition within the bounds of the state machine.  However,
+   * it attempts to enter that state via the state machine.
+   */
+  Response forceTaskState(
+      1: string taskId,
+      2: ScheduleStatus status,
+      3: SessionKey session)
+
+  /** Immediately writes a storage snapshot to disk. */
+  Response performBackup(1: SessionKey session)
+
+  /** Lists backups that are available for recovery. */
+  Response listBackups(1: SessionKey session)
+
+  /** Loads a backup to an in-memory storage.  This must precede all other recovery operations. */
+  Response stageRecovery(1: string backupId, 2: SessionKey session)
+
+  /** Queries for tasks in a staged recovery. */
+  Response queryRecovery(1: TaskQuery query, 2: SessionKey session)
+
+  /** Deletes tasks from a staged recovery. */
+  Response deleteRecoveryTasks(1: TaskQuery query, 2: SessionKey session)
+
+  /** Commits a staged recovery, completely replacing the previous storage state. */
+  Response commitRecovery(1: SessionKey session)
+
+  /** Unloads (aborts) a staged recovery. */
+  Response unloadRecovery(1: SessionKey session)
+
+  /** Put the given hosts into maintenance mode. */
+  Response startMaintenance(1: Hosts hosts, 2: SessionKey session)
+
+  /** Ask scheduler to begin moving tasks scheduled on given hosts. */
+  Response drainHosts(1: Hosts hosts, 2: SessionKey session)
+
+  /** Retrieve the current maintenance states for a group of hosts. */
+  Response maintenanceStatus(1: Hosts hosts, 2: SessionKey session)
+
+  /** Set the given hosts back into serving mode. */
+  Response endMaintenance(1: Hosts hosts, 2: SessionKey session)
+
+  /** Start a storage snapshot and block until it completes. */
+  Response snapshot(1: SessionKey session)
+
+  /**
+   * Forcibly rewrites the stored definition of user configurations.  This is intended to be used
+   * in a controlled setting, primarily to migrate pieces of configurations that are opaque to the
+   * scheduler (e.g. executorConfig).
+   * The scheduler may do some validation of the rewritten configurations, but it is important
+   * that the caller take care to provide valid input and alter only necessary fields.
+   */
+  Response rewriteConfigs(1: RewriteConfigsRequest request, 2: SessionKey session)
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift b/api/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
new file mode 100644
index 0000000..a2c230f
--- /dev/null
+++ b/api/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
@@ -0,0 +1,28 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace java org.apache.aurora.gen.comm
+namespace py gen.apache.aurora.comm
+
+include "api.thrift"
+
+// Thrift interface to define the communication between the scheduler and executor.
+
+// Message sent from the scheduler to the executor, indicating that some
+// task history associated with the host may have been purged, and the
+// executor should only retain tasks associated with the provided tasks IDs.
+struct AdjustRetainedTasks {
+  2: map<string, api.ScheduleStatus> retainedTasks  // All tasks that the executor should
+                                                    // retain, and their statuses.
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/aurora/gen/storage.thrift
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/aurora/gen/storage.thrift b/api/src/main/thrift/org/apache/aurora/gen/storage.thrift
new file mode 100644
index 0000000..3798797
--- /dev/null
+++ b/api/src/main/thrift/org/apache/aurora/gen/storage.thrift
@@ -0,0 +1,250 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace java org.apache.aurora.gen.storage
+namespace py gen.apache.aurora.storage
+
+include "api.thrift"
+
+// Thrift object definitions for messages used for mesos storage.
+
+// Ops that are direct representations of the data needed to perform local storage mutations.
+struct SaveFrameworkId {
+  1: string id
+}
+
+struct SaveAcceptedJob {
+  1: string managerId
+  2: api.JobConfiguration jobConfig
+}
+
+struct SaveLock {
+  1: api.Lock lock
+}
+
+struct RemoveLock {
+  1: api.LockKey lockKey
+}
+
+struct RemoveJob {
+  2: api.JobKey jobKey
+}
+
+struct SaveTasks {
+  1: set<api.ScheduledTask> tasks
+}
+
+struct RewriteTask {
+  1: string taskId
+  2: api.TaskConfig task
+}
+
+struct RemoveTasks {
+  1: set<string> taskIds
+}
+
+struct SaveQuota {
+  1: string role
+  2: api.ResourceAggregate quota
+}
+
+struct RemoveQuota {
+  1: string role
+}
+
+struct SaveHostAttributes {
+  1: api.HostAttributes hostAttributes
+}
+
+struct SaveJobUpdate {
+  1: api.JobUpdate jobUpdate
+  2: string lockToken
+}
+
+struct StoredJobUpdateDetails {
+  1: api.JobUpdateDetails details
+  /** ID of the lock associated with this update. */
+  2: string lockToken
+}
+
+struct SaveJobUpdateEvent {
+  1: api.JobUpdateEvent event
+  /** ID of the lock associated with this update. */
+  2: string updateId
+}
+
+struct SaveJobInstanceUpdateEvent {
+  1: api.JobInstanceUpdateEvent event
+  2: string updateId
+}
+
+struct PruneJobUpdateHistory {
+  1: i32 perJobRetainCount
+  2: i64 historyPruneThresholdMs
+}
+
+union Op {
+  1: SaveFrameworkId saveFrameworkId
+  2: SaveAcceptedJob saveAcceptedJob
+  5: RemoveJob removeJob
+  6: SaveTasks saveTasks
+  7: RemoveTasks removeTasks
+  8: SaveQuota saveQuota
+  9: RemoveQuota removeQuota
+  10: SaveHostAttributes saveHostAttributes
+  11: RewriteTask rewriteTask
+  12: SaveLock saveLock
+  13: RemoveLock removeLock
+  14: SaveJobUpdate saveJobUpdate
+  15: SaveJobUpdateEvent saveJobUpdateEvent
+  16: SaveJobInstanceUpdateEvent saveJobInstanceUpdateEvent
+  17: PruneJobUpdateHistory pruneJobUpdateHistory
+}
+
+// The current schema version ID.  This should be incremented each time the
+// schema is changed, and support code for schema migrations should be added.
+const i32 CURRENT_SCHEMA_VERSION = 1
+
+// Represents a series of local storage mutations that should be applied in a single atomic
+// transaction.
+struct Transaction {
+  1: list<Op> ops
+  2: i32 schemaVersion
+}
+
+struct StoredJob {
+  1: string jobManagerId
+  3: api.JobConfiguration jobConfiguration
+}
+
+struct SchedulerMetadata {
+  1: string frameworkId
+  // The SHA of the repo.
+  2: string revision
+  // The tag of the repo.
+  3: string tag
+  // The timestamp of the build.
+  4: string timestamp
+  // The user who built the scheduler
+  5: string user
+  // The machine that built the scheduler
+  6: string machine
+  7: api.APIVersion version
+}
+
+struct QuotaConfiguration {
+  1: string role
+  2: api.ResourceAggregate quota
+}
+
+// Represents a complete snapshot of local storage data suitable for restoring the local storage
+// system to its state at the time the snapshot was taken.
+struct Snapshot {
+
+  // The timestamp when the snapshot was made in milliseconds since the epoch.
+  1: i64 timestamp
+
+  3: set<api.HostAttributes> hostAttributes
+  4: set<api.ScheduledTask> tasks
+  5: set<StoredJob> jobs
+  6: SchedulerMetadata schedulerMetadata
+  8: set<QuotaConfiguration> quotaConfigurations
+  9: set<api.Lock> locks
+  10: set<StoredJobUpdateDetails> jobUpdateDetails
+}
+
+// A message header that calls out the number of expected FrameChunks to follow to form a complete
+// message.
+struct FrameHeader {
+
+  // The number of FrameChunks following this FrameHeader required to reconstitute its message.
+  1: i32 chunkCount
+
+  // The MD5 checksum over the binary blob that was chunked across chunkCount chunks to decompose
+  // the message.
+  2: binary checksum
+}
+
+// A chunk of binary data that can be assembled with others to reconstitute a fully framed message.
+struct FrameChunk {
+  2: binary data
+}
+
+// Frames form a series of LogEntries that can be re-assembled into a basic log entry type like a
+// Snapshot.  The Frame protocol is that a single FrameHeader is followed by one or more FrameChunks
+// that can be re-assembled to obtain the binary content of a basic log entry type.
+//
+// In the process of reading a Frame, invalid data should always be logged and skipped as it may
+// represent a failed higher level transaction where a FrameHeader successfully appends but not all
+// the chunks required to complete the full message frame successfully commit.  For example: if a
+// Snaphsot is framed, it might break down into 1 FrameHeader followed by 5 FrameChunks.  It could
+// be that the FrameHeader and 2 chunks get written successfully, but the 3rd and subsequent chunks
+// fail to append.  In this case, the storage mechanism would throw to indicate a failed transaction
+// at write-time leaving a partially framed message in the log stream that should be skipped over at
+// read-time.
+union Frame {
+  1: FrameHeader header
+  2: FrameChunk chunk
+}
+
+// A ScheduledTask with its assignedTask.task field set to null. Deserializers must fill in
+// assignedTask.task with the TaskConfig identified by taskConfigId (which is an index into the
+// DeduplicatedSnapshot's taskConfigs list).
+struct DeduplicatedScheduledTask {
+  1: api.ScheduledTask partialScheduledTask
+  2: i32 taskConfigId
+}
+
+// A Snapshot that has had duplicate TaskConfig structs removed to save space. The
+// partialSnapshot field is a normal Snapshot with the tasks field set to null. To create the
+// full Snapshot deserializers must fill in this field with the result of recreating each
+// partial task using the referenced entry in taskConfigs.
+struct DeduplicatedSnapshot {
+   // Snapshot with its tasks field unset.
+   1: Snapshot partialSnapshot
+   // ScheduledTasks that have had their assignedTask.task field replaced with an ID to save space.
+   2: list<DeduplicatedScheduledTask> partialTasks
+   // Ordered list of taskConfigs. The taskConfigId field of DeduplicatedScheduledTask is an index
+   // into this.
+   3: list<api.TaskConfig> taskConfigs
+}
+
+// A scheduler storage write-ahead log entry consisting of no-ops to skip over or else snapshots or
+// transactions to apply.  Any entry type can also be chopped up into frames if the entry is too big
+// for whatever reason.
+union LogEntry {
+  // The full state of the scheduler at some point-in-time. Transactions appearing before this
+  // entry in the log can be ignored.
+  1: Snapshot snapshot
+
+  // An incremental update to apply to the scheduler storage.
+  2: Transaction transaction
+
+  // The value should be ignored - both true and false signal an equivalent no operation marker.
+  3: bool noop;
+
+  // A frame that can be reassembled with others to form a complete LogEntry.
+  4: Frame frame
+
+  // A LogEntry that is first serialized in the thrift binary format,
+  // then compressed using the "deflate" compression format.
+  // Deflated entries are expected to be un-framed.  They may be pieced together by multiple frames,
+  // but the contents of the deflated entry should not be a Frame.
+  5: binary deflatedEntry
+
+  // The full state of the scheduler at some point-in-time, in a compact layout. Transactions
+  // appearing before this entry in the log can be ignored.
+  6: DeduplicatedSnapshot deduplicatedSnapshot
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/aurora/gen/test.thrift
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/aurora/gen/test.thrift b/api/src/main/thrift/org/apache/aurora/gen/test.thrift
new file mode 100644
index 0000000..cd08f28
--- /dev/null
+++ b/api/src/main/thrift/org/apache/aurora/gen/test.thrift
@@ -0,0 +1,259 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace java org.apache.aurora.gen.test
+namespace py gen.apache.aurora.test
+
+// Test data for Thrift interface definition for the Twitter Mesos Scheduler.
+
+// Test data for job path identifiers.
+const set<string> VALID_IDENTIFIERS = ["devel",
+                                       "dev-prod",
+                                       "Dev_prod-",
+                                       "deV.prod",
+                                       ".devprod.."]
+
+const set<string> INVALID_IDENTIFIERS = ["dev/prod",
+                                         "dev prod",
+                                         "/dev/prod",
+                                         "///",
+                                         "new\nline",
+                                         "    hello world."]
+
+
+// Valid cron schedules (taken from a list of cron schedules running at Twitter).
+const set<string> VALID_CRON_SCHEDULES = [
+    "25 */2 * * *",
+    "05 */1 * * *",
+    "5 */4 * * *",
+    "42 * * * *",
+    "30 07 * * *",
+    "28 23 * * 3",
+    "11 * * * *",
+    "23 */2 * * *",
+    "10,40 8,9,10,11 * * *",
+    "22 * * * *",
+    "15 8,13,18 * * *",
+    "15,45 * * * *",
+    "0 */1 * * *",
+    "02 6 * * *",
+    "1 * * * *",
+    "37 */1 * * *",
+    "0 0/3 * * *",
+    "19 12,23 * * *",
+    "41 4,12,20 * * *",
+    "16 09,16 * * *",
+    "17 1,9,17 * * 0",
+    "*/1 * * * *",
+    "0 17,23 * * *",
+    "42 18,21,23,3,7 * * *",
+    "20 12 * * *",
+    "3,13,23,33,43,53 * * * *",
+    "50 07 * * *",
+    "00 22 * * 0,2,5",
+    "6 2,10,18 * * *",
+    "59 */4 * * *",
+    "17 00 * * *",
+    "10 06 * * *",
+    "13,28,43,58 * * * *",
+    "0 */3 * * *",
+    "0 2 * * *",
+    "30 * * * *",
+    "0 8,11,14,17,20 * * *",
+    "10 * * * *",
+    "30 06 * * *",
+    "23 * * * *",
+    "30 9 * * *",
+    "02 6,10,14 * * *",
+    "19 * * * *",
+    "7 12 * * *",
+    "0 * * * *",
+    "*/10 * * * *",
+    "30 14,16,18,20,22 * * *",
+    "0,10,20,30,40,50 * * * *",
+    "30 0,12 * * *",
+    "45 22 * * *",
+    "20 */3 * * *",
+    "14 9,21 * * *",
+    "*/20 * * * *",
+    "1 7,15,23 * * *",
+    "*/2 * * * *",
+    "25 14 * * *",
+    "0 */6 * * *",
+    "30 6 * * *",
+    "0 16,20,0,3,6 * * *",
+    "5,15,25,35,45,55 * * * *",
+    "22 3,15 * * *",
+    "0 1,3,5,7,9,11,13 * * *",
+    "14 8,17 * * *",
+    "30 21 * * 0,2,5",
+    "44 23 * * *",
+    "35,50 * * * *",
+    "10 01,07,13,19 * * *",
+    "1 14 * * *",
+    "29 9,16,22 * * *",
+    "12 2 * * *",
+    "0 22 * * *",
+    "1 */6 * * *",
+    "0 20 * * 4",
+    "0 9,12,15,18,21 * * *",
+    "30 2 * * *",
+    "15 * * * *",
+    "0 20 * * 1",
+    "0 */12 * * *",
+    "17 0,5,17,20 * * *",
+    "0 20 * * *",
+    "30 18,23 * * MON-FRI",
+    "0 22 * * 1",
+    "35 23 * * *",
+    "55 03 * * *",
+    "23 3,15,22 * * *",
+    "20 13 * * *",
+    "30 11 * * *",
+    "*/5 * * * *",
+    "*/6 * * * *",
+    "0 2,4,6,8,10,12 * * *",
+    "10 02,08,12 * * *",
+    "0 11 * * *",
+    "05 02,08,12 * * *",
+    "10 11 * * *",
+    "22 */6 * * *",
+    "00 08 * * *",
+    "0 2 1 * *",
+    "30 19 * * 1,4",
+    "0 */4 * * *",
+    "10,30,50 * * * *",
+    "22 22 * * *",
+    "00 11 * * *",
+    "29 16,17,18,22 * * *",
+    "30 22 * * *",
+    "05 * * * *",
+    "0 23 * * 3",
+    "15 */12 * * *",
+    "30 19 * * 2,5",
+    "*/30 * * * *",
+    "22 6,18 * * *",
+    "0 5 * * *",
+    "15 8 * * 1,3,5",
+    "0 8 * * *",
+    "10 0 * * *",
+    "40 11 * * *",
+    "0 0 * * 1",
+    "17 2,4,11,18 * * *",
+    "30 0,8,16 * * *",
+    "27 8,20 * * *",
+    "0 0 * * *",
+    "20 18 * * 2,4,6",
+    "15 11 * * 2,6",
+    "0,15,30,45 * * * *",
+    "45 * * * *",
+    "36 * * * *",
+    "45 17 * * 0,2,4",
+    "0 */2 * * *",
+    "12 3,15,22 * * *",
+    "2,7,12,17,22,27,32,37,42,47,52,57 * * * *",
+    "0 23 2-31 * *",
+    "10 16 * * *",
+    "3 * * * *",
+    "42 8,20 * * *",
+    "0 15,19,23,2,5 * * *",
+    "30 10 * * *",
+    "2 2 * * *",
+    "0 12 * * *",
+    "15 17 * * *",
+    "0 7 * * *",
+    "1 2 * * *",
+    "30 19 * * 0,3",
+    "15 10 * * 2,6",
+    "55 */1 * * *",
+    "15 */4 * * *",
+    "0 3,6,9,12,15,18,21 * * *",
+    "11 0 * * *",
+    "0 6 * * *",
+    "0 3 * * *",
+    "20 7,12,17 * * *",
+    "21 * * * *",
+    "58 * * * *",
+    "10 02,08,14,20 * * *",
+    "0 1,2,3,4,5,6,7,8,9,10,11,12,13 * * *",
+    "50,59 * * * *",
+    "30,45 18 * * 1",
+    "0 1 * * *",
+    "7 * * * *",
+    "0 14 * * *",
+    "09 22 * * *",
+    "00 17 1-3,5-31 * *",
+    "17 1,9,17 * * 1-6",
+    "45 */4 * * *",
+    "20 2,12,22 * * *",
+    "15 3 * * *",
+    "0 3 1 * *",
+    "42 10 * * *",
+    "12 7 * * *",
+    "1,31 * * * *",
+    "00 01 * * *",
+    "0 9 1 * *",
+    "50 */4 * * *",
+    "43 * * * *",
+    "10,40 9,10,11,12 * * *",
+    "35 * * * *",
+    "8 1,9,17 * * *",
+    "45,54 * * * *",
+    "49 6,18 * * *",
+    "25 12,18,23 * * *",
+    "20 18 * * 1,3,5",
+    "45 17 * * 2,4",
+    "0 17 * * *",
+    "30 */6 * * *",
+    "52 0,6,12,18 * * *",
+    "*/15 * * * *",
+    "1-56/5 * * * *",
+    "0 2,3,4,5,6,7,8,9,10,11,12,13 * * *",
+    "12 * * * *",
+    "*/3 * * * *",
+    "*/4 * * * *",
+    "3 1,9,17 * * *",
+    "00 14 * * *",
+    "10 05 * * *",
+    "8 21 * * *",
+    "0 13 * * 2",
+    "0 13 * * 3",
+    "0 19 * * *",
+    "0 21 * * *",
+    "23 */4 * * *",
+    "10 3,11,19 * * *",
+    "* * * * *",
+    "30 14 * * *",
+    "03,18,33,48 * * * *",
+    "0 11,23 * * *",
+    "30 20 * * 0,2,5",
+    "30 02,08,12 * * *",
+    "45 1,3,5,7,9,11,13,15,17,19,21,23 * * *",
+    "7 */2 * * *",
+    "30 16 * * *",
+    "5 * * * *",
+    "04 06,12,18,23 * * *",
+    "00 */2 * * *",
+    "00 06,15 * * *",
+    "35 */2 * * *",
+    "1 5,13,21 * * *",
+    "47 */2 * * *",
+    "10 21 * * *",
+    "00 21 * * *",
+    "26 2,6,10,14,18,22 * * *",
+    "00 11 * * 0,2,5",
+    "0 18,22 * * MON-FRI",
+    "00 21 * * 0,2,5",
+    "0 17-19 * * 1",
+    "15 9 * * 1,3,5"]

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/thermos/BUILD
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/thermos/BUILD b/api/src/main/thrift/org/apache/thermos/BUILD
new file mode 100644
index 0000000..d0d789a
--- /dev/null
+++ b/api/src/main/thrift/org/apache/thermos/BUILD
@@ -0,0 +1,25 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+
+python_thrift_library(
+  name = 'py-thrift',
+  sources = ['thermos_internal.thrift'],
+  provides = setup_py(
+    name = 'apache.gen.thermos',
+    version = open(os.path.join(get_buildroot(), '.auroraversion')).read().strip().upper(),
+    description = 'Autogenerated Thermos thrift schemas.',
+  )
+)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/api/src/main/thrift/org/apache/thermos/thermos_internal.thrift
----------------------------------------------------------------------
diff --git a/api/src/main/thrift/org/apache/thermos/thermos_internal.thrift b/api/src/main/thrift/org/apache/thermos/thermos_internal.thrift
new file mode 100644
index 0000000..2c449a4
--- /dev/null
+++ b/api/src/main/thrift/org/apache/thermos/thermos_internal.thrift
@@ -0,0 +1,99 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace py gen.apache.thermos
+
+enum ProcessState {
+  // normal state
+  WAITING   = 0   // blocked on execution dependencies or footprint restrictions
+  FORKED    = 1   // starting, need to wait for signal from Process that it's running
+  RUNNING   = 2   // currently running
+  SUCCESS   = 3   // returncode == 0
+  KILLED    = 4   // Killed by user action or task failure, runner teardown.
+
+  // abnormal states
+  FAILED    = 5   // returncode != 0
+  LOST      = 6   // the coordinator either died or some condition caused us to lose it
+                  // e.g. reboot.
+}
+
+struct ProcessStatus {
+  // Sequence number, must be monotonically increasing for all
+  // ProcessState messages for a particular process across all runs.
+  1: i64             seq
+
+  // Process name
+  3: string          process
+
+  5: ProcessState    state
+
+  // WAITING -> FORKED
+ 10: i32             coordinator_pid
+ 11: double          fork_time
+
+  // FORKED -> RUNNING
+  6: double          start_time
+  7: i32             pid
+
+  // RUNNING -> {FINISHED, FAILED, KILLED}
+  8: double          stop_time
+  9: i32             return_code
+
+  // {FORKED, RUNNING} -> LOST nothing happens.  this ProcessState ceases to exist.
+  // Doesn't count against the run total.
+}
+
+enum TaskState {
+  ACTIVE     = 0  // Regular plan is being executed
+  CLEANING   = 5  // Regular plan has failed/finished and is being cleaned up
+                  // Existing processes get SIGTERMs.
+                  // Once all processes are finished, => FINALIZING
+                  // If finalization wait overflows, SIGKILL and transition to terminal.
+  FINALIZING = 6  // Finalizing plan is being executed
+  SUCCESS    = 1  // Task has succeeded
+  FAILED     = 2  // Task has failed
+  KILLED     = 3  // Task has been killed
+  LOST       = 4  // Task is lost (special state reserved for garbage collection.)
+}
+
+struct TaskStatus {
+  1: TaskState state
+  2: i64       timestamp_ms
+  3: i32       runner_pid
+  4: i32       runner_uid
+}
+
+// The first framed message in the Ckpt stream.
+struct RunnerHeader {
+  1: string task_id
+  2: i64    launch_time_ms  // kill this
+  3: string sandbox
+  7: string log_dir
+  4: string hostname        // kill this
+  5: string user
+  8: i32    uid             // added as a check in case user disappears
+  6: map<string, i64> ports
+}
+
+union RunnerCkpt {
+  1: RunnerHeader       runner_header
+  2: ProcessStatus      process_status
+  3: TaskStatus         task_status
+}
+
+struct RunnerState {
+  1: RunnerHeader header
+  2: list<TaskStatus> statuses
+  3: map<string, list<ProcessStatus>> processes
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/build-support/python/make-pycharm-virtualenv
----------------------------------------------------------------------
diff --git a/build-support/python/make-pycharm-virtualenv b/build-support/python/make-pycharm-virtualenv
index 8f58d4d..85e8137 100755
--- a/build-support/python/make-pycharm-virtualenv
+++ b/build-support/python/make-pycharm-virtualenv
@@ -22,8 +22,8 @@ PROJECT_NAME=${PWD##*/}
 
 pushd "$BUILDROOT"
   ./pants goal dependencies --dependencies-external src/test/python:all > requirements.txt
-  ./pants setup_py src/main/thrift/org/apache/aurora/gen:py-thrift-packaged
-  ./pants setup_py src/main/thrift/org/apache/thermos:py-thrift
+  ./pants setup_py api/src/main/thrift/org/apache/aurora/gen:py-thrift-packaged
+  ./pants setup_py api/src/main/thrift/org/apache/thermos:py-thrift
   source build-support/pants.venv/bin/activate
     pytest_requirement=$(pip freeze | grep pytest==)
     pytest_cov_requirement=$(pip freeze | grep pytest-cov==)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/build-support/release/make-python-sdists
----------------------------------------------------------------------
diff --git a/build-support/release/make-python-sdists b/build-support/release/make-python-sdists
index e0d20a1..a7a627f 100755
--- a/build-support/release/make-python-sdists
+++ b/build-support/release/make-python-sdists
@@ -38,8 +38,8 @@ TARGETS=(
   src/main/python/apache/thermos/core
   src/main/python/apache/thermos/monitoring
   src/main/python/apache/thermos/observer
-  src/main/thrift/org/apache/aurora/gen:py-thrift-packaged
-  src/main/thrift/org/apache/thermos:py-thrift
+  api/src/main/thrift/org/apache/aurora/gen:py-thrift-packaged
+  api/src/main/thrift/org/apache/thermos:py-thrift
 )
 
 cd "`git rev-parse --show-toplevel`"

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/build-support/thrift/thriftw
----------------------------------------------------------------------
diff --git a/build-support/thrift/thriftw b/build-support/thrift/thriftw
new file mode 100755
index 0000000..50d6dfd
--- /dev/null
+++ b/build-support/thrift/thriftw
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Wrapper for thrift that attempts to use the system thrift if it's of the expected version,
+# otherwise it bootstraps a new one.
+set -e -u
+
+if [[ $# -lt 1 ]]; then
+  cat <<EOF
+Usage: thriftw EXPECTED_THRIFT_VERSION THRIFT_ARGS...
+
+Run the thrift compiler at EXPECTED_THRIFT_VERSION with THRIFT_ARGS, bootstrapping if necessary.
+EOF
+fi
+expected_version=$1
+shift
+
+HERE=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)
+
+if which thrift >/dev/null 2>&1; then
+  if [[ $(thrift --version) = "Thrift version $expected_version" ]]; then
+    exec thrift "$@"
+  fi
+fi
+
+thrift="$HERE"/thrift-$expected_version/compiler/cpp/thrift
+if [[ ! -x "$thrift" ]]; then
+  make -C "$HERE"
+fi
+exec "$thrift" "$@"

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 9a71d00..f1a3171 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import org.apache.aurora.build.CoverageReportCheck
 
 plugins {
   id 'com.eriwen.gradle.js' version '1.12.1'
@@ -21,28 +22,158 @@ plugins {
 apply plugin: 'application'
 apply plugin: 'checkstyle'
 apply plugin: 'findbugs'
-apply plugin: 'idea'
 apply plugin: 'jacoco'
-apply plugin: 'java'
-apply plugin: 'maven-publish'
 apply plugin: 'pmd'
-apply plugin: 'project-report'
 
-buildDir = 'dist'
-def generatedDir = "$buildDir/generated-src"
-def generatedJavaDir = "$generatedDir/gen-java"
-def generatedJSDir = "$generatedDir/gen-js"
-def generatedResourceDir = "$generatedDir/resources"
-def httpAssetsPath = 'scheduler/assets'
+allprojects {
+  apply plugin: 'java'
+  apply plugin: 'idea'
+  apply plugin: 'maven-publish'
+  apply plugin: 'project-report'
 
-def thriftVersion = '0.9.1'
+  buildDir = 'dist'
 
-compileJava {
-  sourceCompatibility = 1.7
-  targetCompatibility = 1.7
+  repositories {
+    mavenCentral()
+    maven {
+      url 'http://maven.twttr.com/'
+    }
+  }
+
+  compileJava {
+    sourceCompatibility = 1.7
+    targetCompatibility = 1.7
+  }
+
+  group 'org.apache.aurora'
+  version = file("${rootDir}/.auroraversion").text.trim().toUpperCase()
+
+  task sourceJar(type: Jar) {
+    from sourceSets.main.allJava
+  }
+
+  if (project.hasProperty('internalMavenUrl')) {
+    publishing {
+      repositories {
+        maven {
+          credentials {
+            username = internalMavenUser
+            password = internalMavenPass
+          }
+          url internalMavenUrl
+        }
+      }
+    }
+  }
+
+  ext.slf4jRev = '1.6.6'
+  def slf4jApiDep = "org.slf4j:slf4j-api:${slf4jRev}"
+  dependencies {
+    compile slf4jApiDep
+  }
+  ext.gsonRev = '2.2.4'
+  ext.guavaRev = '16.0'
+  ext.thriftRev = '0.9.1'
+
+  configurations {
+    compile {
+      resolutionStrategy {
+        failOnVersionConflict()
+        force slf4jApiDep
+      }
+    }
+  }
 }
 
-tasks.withType(JavaCompile).matching { it.name != 'compileGeneratedJava' }.all {
+project(':api') {
+  apply plugin: org.apache.aurora.build.ThriftPlugin
+  apply plugin: org.apache.aurora.build.ThriftEntitiesPlugin
+
+  task checkPython << {
+    def python27Executable = ['python2.7', 'python'].find { python ->
+      try {
+        def check = "import sys; sys.exit(0 if sys.version_info >= (2,7) and sys.version_info < (3,) else 1)"
+        return [python, "-c", check].execute().waitFor() == 0
+      } catch (IOException e) {
+        return false
+      }
+    }
+
+    if (python27Executable == null) {
+      throw new GradleException('Build requires Python 2.7.')
+    } else {
+      thriftEntities.python = python27Executable
+    }
+  }
+  generateThriftEntitiesJava.dependsOn checkPython
+
+  tasks.withType(Jar) {
+    baseName "aurora-api"
+  }
+
+  publishing {
+    publications {
+      mavenJava(MavenPublication) {
+        from components.java
+
+        artifactId "aurora-api"
+
+        artifact sourceJar {
+          classifier "sources"
+        }
+      }
+    }
+  }
+
+  thrift {
+    version = thriftRev
+    resourcePrefix = 'org/apache/aurora/scheduler/gen/client'
+  }
+
+  thriftEntities {
+    gsonRev = project.gsonRev
+    guavaRev = project.guavaRev
+  }
+
+  idea {
+    module {
+      [thrift.genJavaDir, thriftEntities.genJavaDir].each {
+        sourceDirs += it
+        generatedSourceDirs += it
+      }
+      // These directories must exist, else the plugin omits them from the
+      // generated project. Since this is executed during the configuration
+      // lifecycle phase, dependency tasks have not yet run and created
+      // the directories themselves.
+      // By default, the idea module [1] excludes are set to
+      // [project.buildDir, project.file('.gradle')]
+      // This has the side-effect of also excluding our generated sources [2].  Due to the way
+      // directory exclusion works in idea, you can't exclude a directory and include a child of that
+      // directory. Clearing the excludes seems to have no ill side-effects, making it preferable to
+      // other possible approaches.
+      //
+      // [1] http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html
+      // [2] http://issues.gradle.org/browse/GRADLE-1174
+      excludeDirs = [file(".gradle")]
+      [
+          "classes",
+          "dependency-cache",
+          "docs",
+          "jacoco",
+          "reports",
+          "test-results",
+          "tmp"
+      ].each {
+        excludeDirs << file("$buildDir/$it")
+      }
+    }
+  }
+}
+
+def generatedDir = "$buildDir/generated-src"
+def httpAssetsPath = 'scheduler/assets'
+
+compileJava {
   options.compilerArgs << '-Werror'
   options.compilerArgs << '-Xlint:all'
   // Don't fail for annotations not claimed by annotation processors.
@@ -55,102 +186,46 @@ task wrapper(type: Wrapper) {
   gradleVersion = project(':buildSrc').GRADLE_VERSION
 }
 
-task sourceJar(type: Jar) {
-  from sourceSets.main.allJava
-}
-
-group 'org.apache.aurora'
-version = file('.auroraversion').text.trim().toUpperCase()
-
+// TODO(ksweeney): Consider pushing this down to API - the scheduler implementation itself should
+// only be consumed as an application.
 publishing {
   publications {
-    maven(MavenPublication) {
-      artifactId 'aurora-scheduler'
+    mavenJava(MavenPublication) {
       from components.java
 
+      artifactId 'aurora-scheduler'
+
       artifact sourceJar {
         classifier "sources"
       }
     }
   }
-  if (project.hasProperty('internalMavenUrl')) {
-    repositories {
-      maven {
-        credentials {
-          username = internalMavenUser
-          password = internalMavenPass
-        }
-        url internalMavenUrl
-      }
-    }
-  }
-}
-
-repositories {
-  mavenCentral()
-  maven {
-    url 'http://maven.twttr.com/'
-  }
 }
 
 sourceSets {
-  test {
-    resources {
-      srcDir 'src/main/resources'
-      srcDir 'src/test/resources'
-      srcDir '3rdparty/javascript'
-      srcDir generatedJSDir
-      srcDir generatedResourceDir
-    }
-  }
-  generated {
-    java.srcDirs = [generatedDir]
-  }
   main {
-    compileClasspath += sourceSets.generated.output
     resources {
       srcDir '3rdparty/javascript'
-      srcDir generatedJSDir
-      srcDir generatedResourceDir
     }
   }
-  test {
-    compileClasspath += sourceSets.generated.output
-    runtimeClasspath += sourceSets.generated.output
-  }
-}
-/*  A note on libthrift: All of com.twitter.common depends on libthrift 0.5.x. We depend on
-    libthrift 0.9.x. There are binary incompatibilities between the two versions and resolving
-    them involved forking com.twitter.common classes into Aurora to use the new libthrift API. Be
-    very cautious when either upgrading libthrift or com.twitter.common dependencies!!!
- */
-
-jar {
-  from sourceSets.generated.output
-  manifest {
-    attributes('Created-By': 'Gradle')
-    attributes('Main-Class': 'org.apache.aurora.scheduler.app.SchedulerMain')
-  }
 }
 
 dependencies {
   def guiceRev = '3.0'
   def jerseyRev = '1.18.1'
   def log4jRev = '1.2.17'
-  def slf4jRev = '1.6.1'
   def junitRev = '4.11'
 
-  def gsonDep = 'com.google.code.gson:gson:2.2.4'
-  def guavaDep = 'com.google.guava:guava:16.0'
+  def gsonDep = "com.google.code.gson:gson:${gsonRev}"
+  def guavaDep = "com.google.guava:guava:${guavaRev}"
   // NOTE: We are using the jetty 7.x series due to a large number of dependencies impacted
   // by 8.x and later resulting from using newer javax.servlet servlet-api.
   def jettyDep = '7.6.15.v20140411'
-  def thriftLib = "org.apache.thrift:libthrift:${thriftVersion}"
+
+  compile project(':api')
 
   compile 'aopalliance:aopalliance:1.0'
   compile 'com.google.code.findbugs:jsr305:2.0.1'
-  compile gsonDep
-  compile guavaDep
   compile "com.google.inject:guice:${guiceRev}"
   compile "com.google.inject.extensions:guice-assistedinject:${guiceRev}"
   compile 'com.google.protobuf:protobuf-java:2.5.0'
@@ -165,7 +240,6 @@ dependencies {
   compile "log4j:log4j:${log4jRev}"
   compile 'org.antlr:stringtemplate:3.2.1'
   compile 'org.apache.mesos:mesos:0.20.1'
-  compile thriftLib
   compile 'org.apache.zookeeper:zookeeper:3.3.4'
   compile "org.eclipse.jetty:jetty-rewrite:${jettyDep}"
   compile "org.eclipse.jetty:jetty-server:${jettyDep}"
@@ -174,7 +248,6 @@ dependencies {
   compile 'org.mybatis:mybatis:3.2.7'
   compile 'org.mybatis:mybatis-guice:3.6'
   compile 'org.quartz-scheduler:quartz:2.2.1'
-  compile "org.slf4j:slf4j-api:${slf4jRev}"
   compile "org.slf4j:slf4j-jdk14:${slf4jRev}"
   compile 'com.twitter.common.logging:log4j:0.0.7'
   compile 'com.twitter.common.zookeeper.guice:client-flagged:0.0.5'
@@ -212,24 +285,18 @@ dependencies {
   testCompile 'com.twitter.common:zookeeper-testing:0.0.45'
   testCompile "junit:junit:${junitRev}"
 
-  generatedCompile gsonDep
-  generatedCompile guavaDep
-  generatedCompile thriftLib
-
   configurations.compile {
     exclude module: 'junit-dep'
     resolutionStrategy {
-      failOnVersionConflict()
-
       def forceDepVersions = [
         // Force versions based on the dependencies we use from above
         'com.google.code.gson:gson': '2.2.4',
-        'org.slf4j:slf4j-api' : slf4jRev,
         'log4j:log4j' : log4jRev,
-        'org.apache.thrift:libthrift' : thriftVersion,
         'junit:junit' : junitRev,
         // Force versions based on inter-dependency collisions
         'org.hamcrest:hamcrest-core' : '1.3',
+        'org.apache.thrift:libthrift': thriftRev,
+        'org.slf4j:slf4j-jdk14': slf4jRev,
       ]
 
       force forceDepVersions.collect { dep, ver -> "$dep:$ver" }
@@ -254,7 +321,7 @@ codeQualityTasks.each {
 }
 
 checkstyle {
-  sourceSets = [ sourceSets.main , sourceSets.test]
+  sourceSets = [sourceSets.main , sourceSets.test]
 }
 
 tasks.withType(FindBugs) {
@@ -288,36 +355,6 @@ pmd {
   consoleOutput = true
 }
 
-task checkPython() {
-  def py_versions = ['python2.7', 'python2.6', 'python']
-
-  project.ext.set('py', '')
-
-  py_versions.each { python_exe ->
-    if (project.py.isEmpty()) {
-      // Look for the first version of python listed in py_versions greater than 2.6.
-      // Execute will throw an exception if that python command does not exist,
-      // and set project.py to be empty
-      try {
-        def check = "import sys; sys.stdout.write(str(sys.version_info > (2,6) and sys.version_info < (3,)))"
-        def cmd = [python_exe, "-c", check].execute()
-        def output = cmd.in.text.trim()
-
-        if(output.toLowerCase() == 'true') {
-          project.py = python_exe
-        }
-      } catch (Exception e) {
-          project.py = ''
-      }
-    }
-  }
-
-  doLast {
-    if (project.py.isEmpty()) {
-      throw new GradleException('Build requires Python 2.6 or Python 2.7')
-    }
-  }
-}
 
 /**
  * There is a jshint target recommended in the README for gradle-js-plugin
@@ -353,144 +390,38 @@ task jsHint(type:com.eriwen.gradle.js.tasks.JsHintTask) {
 }
 tasks.checkstyleMain.dependsOn(jsHint)
 
-/**
- * Check if Apache Thrift is all ready installed and is the same version as we
- * depend on, otherwise compile the version in build-support. project.thrift will
- * contain the path to the thrift executable when finished
- */
-task bootstrapThrift {
-  logging.captureStandardOutput LogLevel.INFO
-
-  project.ext.set('thrift', '')
-
-  try {
-    // Attempt to run thrift and get the version string back. if no version of thrift is available
-    // execute will throw an exception, catch and set project.thrift as empty to build the local version
-    def output = "thrift --version".execute().text.trim()
-    if(output == "Thrift version ${thriftVersion}") {
-      project.thrift = 'thrift'
-    }
-  } catch (IOException e) {
-    project.thrift = ''
-  }
-
-  // If thrift was not found or was the wrong version build our local copy
-  if (project.thrift.isEmpty()) {
-    project.thrift = "build-support/thrift/thrift-${thriftVersion}/compiler/cpp/thrift"
-
-    inputs.file file(project.thrift)
-    outputs.dir file(project.thrift)
-    doLast {
-      exec {
-        executable = 'make'
-        args = ['-C', 'build-support/thrift']
-      }
-    }
-  }
-}
-
-// TODO(wfarner): Extract this into a task under buildSrc/
-task generateSources(dependsOn: ['bootstrapThrift', 'checkPython']) {
-  ext.thriftDir = 'src/main/thrift/org/apache/aurora/gen'
-  def thriftFiles = fileTree(dir: thriftDir).matching { include '**/*.thrift' }
-  def codeGenerator = 'src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py';
-  ext.inputFiles = thriftFiles + files(codeGenerator)
-  ext.outputDir = file(generatedDir)
-  ext.jsOutputDir = file("$generatedJSDir/$httpAssetsPath/js")
-  inputs.file inputFiles
-  outputs.dir outputDir
-  doLast {
-    outputDir.exists() || outputDir.mkdirs()
-    thriftFiles.each { File file ->
-      exec {
-        executable = project.thrift
-        args = ['--gen', 'java:hashcode,private-members', '-o', outputDir, file]
-      }
-    }
-    exec {
-      executable = project.py
-      args = [codeGenerator,
-              'src/main/thrift/org/apache/aurora/gen/api.thrift',
-              generatedJavaDir,
-              "$generatedResourceDir/$httpAssetsPath"]
-    }
-
-    // Generate thrift javascript separately since we don't need all IDLs, and we want to place
-    // sources in the layout for assets served by the scheduler.
-    jsOutputDir.exists() || jsOutputDir.mkdirs()
-    exec {
-      executable = project.thrift
-      args = ['--gen', 'js:jquery', '-out', jsOutputDir, "$thriftDir/api.thrift"]
-    }
-  }
-}
-
-compileGeneratedJava {
-  dependsOn generateSources
-}
-
-compileJava.source sourceSets.main.java
-
 tasks.withType(Test) {
   maxParallelForks = Runtime.runtime.availableProcessors()
 }
 
-ideaProject.dependsOn generateSources
-
 idea {
   project {
     vcs = 'Git'
   }
-  module {
-    def codegenDirs = [file(generatedJavaDir)]
-
-    // These directories must exist, else the plugin omits them from the
-    // generated project. Since this is executed during the configuration
-    // lifecycle phase, dependency tasks have not yet run and created
-    // the directories themselves.
-    codegenDirs.each { File codegenDir ->
-      codegenDir.mkdirs()
-    }
-
-    // By default, the idea module [1] excludes are set to
-    // [project.buildDir, project.file('.gradle')]
-    // This has the side-effect of also excluding our generated sources [2].  Due to the way
-    // directory exclusion works in idea, you can't exclude a directory and include a child of that
-    // directory. Clearing the excludes seems to have no ill side-effects, making it preferable to
-    // other possible approaches.
-    //
-    // [1] http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html
-    // [2] http://issues.gradle.org/browse/GRADLE-1174
-    excludeDirs = [file("$buildDir/reports"), file("$buildDir/test-results")]
-    sourceDirs += codegenDirs
-
-    // For some reason src/main/resources is marked as both a production source and a test source
-    // directory. In order to run the local scheduler from IntelliJ the resources directory must not
-    // be marked as test sources, so we make it explicit that it's only a production source.
-    testSourceDirs -= file("src/main/resources")
-  }
 }
 
 // Configuration parameters for the application plugin.
 applicationName = 'aurora-scheduler'
 mainClassName = 'org.apache.aurora.scheduler.app.SchedulerMain'
 
-tasks.withType(nl.javadude.gradle.plugins.license.License).each { licenseTask ->
-  licenseTask.setSource files("$projectDir/src/main/java", "$projectDir/src/test/java")
+// TODO(ksweeney): Configure this to scan resources as well.
+tasks.withType(nl.javadude.gradle.plugins.license.License).each {
+  it.source = files("$projectDir/src/main/java", "$projectDir/src/test/java")
 }
 
 license {
   header rootProject.file('config/checkstyle/apache.header')
   strictCheck true
   skipExistingHeaders true
-  ext.year = Calendar.getInstance().get(Calendar.YEAR)
 }
 
 def reportPath = "$buildDir/reports/jacoco/test"
 jacocoTestReport {
   group = "Reporting"
   description = "Generate Jacoco coverage reports after running tests."
-  additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
+
+  sourceDirectories = sourceSets.main.java
+  classDirectories = files("$buildDir/classes/main")
   reports {
     xml.enabled true
   }
@@ -508,19 +439,7 @@ task analyzeReport(type: CoverageReportCheck) {
 }
 jacocoTestReport.finalizedBy analyzeReport
 
-task FlagSchemaChanges(type: Test) << {
-  exec {
-    executable = 'bash'
-    args = ['src/test/sh/org/apache/aurora/verify_thrift_checksum.sh']
-  }
-}
-
-javadoc {
-  classpath += sourceSets.generated.output
-}
-
 run {
-  classpath += sourceSets.generated.output
-  classpath += sourceSets.test.output
   main = 'org.apache.aurora.scheduler.app.local.LocalSchedulerMain'
+  classpath += sourceSets.test.output
 }


[2/3] incubator-aurora git commit: Extract thrift into an API subproject.

Posted by ke...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy b/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
deleted file mode 100644
index f233153..0000000
--- a/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import org.gradle.api.DefaultTask
-import org.gradle.api.GradleException
-import org.gradle.api.tasks.TaskAction
-
-/**
- * A task that analyzes the XML coverage report from JaCoCo and fails the build if code coverage
- * metrics are not met.
- */
-class CoverageReportCheck extends DefaultTask {
-
-  // The XML coverage report file.
-  def coverageReportFile
-
-  // Minimum ratio of instructions covered, [0, 1.0].
-  def minInstructionCoverage
-
-  // Minimum ratio of branches covered, [0, 1.0].
-  def minBranchCoverage
-
-  // Classes that may be allowed to have zero test coverage.
-  def legacyClassesWithoutCoverage
-
-  // The amount of wiggle room when requiring min coverage be raised.
-  def epsilon = 0.005
-
-  private def computeCoverage(counterNodes, type) {
-    def node = counterNodes.find { it.@type == type }
-    def missed = node.@missed.toInteger()
-    def covered = node.@covered.toInteger()
-    return ((double) covered) / (missed + covered)
-  }
-
-  def checkThresholds(coverage, minCoverage, type) {
-    if (coverage < minCoverage) {
-      return "$type coverage is $coverage, but must be greater than $minCoverage"
-    } else {
-      def floored = Math.floor(coverage * 100) / 100
-      if (floored > (minCoverage + epsilon)) {
-        println("$type coverage of $floored exceeds min instruction coverage of $minCoverage"
-            + " by more than $epsilon, please raise the threshold!")
-      } else {
-        println("$type coverage of $coverage exceeds minimum coverage of $minCoverage.")
-      }
-    }
-  }
-
-  def checkGlobalCoverage(coverageCounts) {
-    def coverageErrors = [
-        [computeCoverage(coverageCounts, 'INSTRUCTION'), minInstructionCoverage, 'Instruction'],
-        [computeCoverage(coverageCounts, 'BRANCH'), minBranchCoverage, 'Branch']
-    ].collect() {
-      return checkThresholds(*it)
-    }.findAll()
-
-    if (!coverageErrors.isEmpty()) {
-      throw new GradleException(coverageErrors.join('\n'))
-    }
-  }
-
-  def checkClassCoverage(coverageReport) {
-    def coverageErrors = coverageReport.package.class.collect { cls ->
-      // javac inserts a synthetic constructor for anonymous classes, and jacoco tends to mark
-      // these as covered in some cases, leading to flaky behavior.  We work around that by
-      // collecting the coverage count for each method in each class, omitting the default
-      // constructor for anonymous classes.  Anonymous classes are identified by their name,
-      // which we expect to be of the form 'Something$1'.  Jacoco names default constructors
-      // '<init>', so we filter based on that.
-      def isAnonymous = { c -> c.@name ==~ /.*\$\d+/ }
-      def methodFilter = isAnonymous(cls) ? { m -> m.@name != '<init>' } : { true }
-
-      def matchedMethods = cls.method.findAll(methodFilter)
-      if (isAnonymous(cls) && matchedMethods.isEmpty()) {
-        // Ignore anonymous classes that only have a constructor. This will avoid tripping for
-        // things like TypeLiteral and Clazz.
-        if (cls.@name in legacyClassesWithoutCoverage) {
-          return 'Please remove ' + cls.@name + ' from the legacyClassesWithoutCoverage list' \
-              + ', this check does not apply for constructor-only anonymous classes.'
-        } else {
-          return null
-        }
-      }
-
-      def covered = matchedMethods.collect { m ->
-        m.counter.find({ c -> c.@type == 'INSTRUCTION' }).@covered.toInteger()}.sum(0)
-
-      if (cls.@name in legacyClassesWithoutCoverage) {
-        if (covered != 0) {
-          return 'Thanks for adding the first test coverage to: ' + cls.@name \
-              + ' please remove it from the legacyClassesWithoutCoverage list'
-        }
-      } else if (covered == 0) {
-        return 'Test coverage missing for ' + cls.@name
-      }
-      return null
-    }.findAll()  // Filter nulls.
-    if (!coverageErrors.isEmpty()) {
-      throw new GradleException(coverageErrors.join('\n'))
-    }
-  }
-
-  @TaskAction
-  def analyze() {
-    def parser = new XmlSlurper()
-    parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
-    // Avoid trying to load the DTD for the XML document, which does not exist.
-    parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
-
-    def coverageReport = parser.parse(coverageReportFile)
-
-    checkGlobalCoverage(coverageReport.counter)
-    checkClassCoverage(coverageReport)
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy b/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
new file mode 100644
index 0000000..85210fa
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
@@ -0,0 +1,128 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.build
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * A task that analyzes the XML coverage report from JaCoCo and fails the build if code coverage
+ * metrics are not met.
+ */
+class CoverageReportCheck extends DefaultTask {
+
+  // The XML coverage report file.
+  def coverageReportFile
+
+  // Minimum ratio of instructions covered, [0, 1.0].
+  def minInstructionCoverage
+
+  // Minimum ratio of branches covered, [0, 1.0].
+  def minBranchCoverage
+
+  // Classes that may be allowed to have zero test coverage.
+  def legacyClassesWithoutCoverage
+
+  // The amount of wiggle room when requiring min coverage be raised.
+  def epsilon = 0.005
+
+  private def computeCoverage(counterNodes, type) {
+    def node = counterNodes.find { it.@type == type }
+    def missed = node.@missed.toInteger()
+    def covered = node.@covered.toInteger()
+    return ((double) covered) / (missed + covered)
+  }
+
+  def checkThresholds(coverage, minCoverage, type) {
+    if (coverage < minCoverage) {
+      return "$type coverage is $coverage, but must be greater than $minCoverage"
+    } else {
+      def floored = Math.floor(coverage * 100) / 100
+      if (floored > (minCoverage + epsilon)) {
+        println("$type coverage of $floored exceeds min instruction coverage of $minCoverage"
+            + " by more than $epsilon, please raise the threshold!")
+      } else {
+        println("$type coverage of $coverage exceeds minimum coverage of $minCoverage.")
+      }
+    }
+  }
+
+  def checkGlobalCoverage(coverageCounts) {
+    def coverageErrors = [
+        [computeCoverage(coverageCounts, 'INSTRUCTION'), minInstructionCoverage, 'Instruction'],
+        [computeCoverage(coverageCounts, 'BRANCH'), minBranchCoverage, 'Branch']
+    ].collect() {
+      return checkThresholds(*it)
+    }.findAll()
+
+    if (!coverageErrors.isEmpty()) {
+      throw new GradleException(coverageErrors.join('\n'))
+    }
+  }
+
+  def checkClassCoverage(coverageReport) {
+    def coverageErrors = coverageReport.package.class.collect { cls ->
+      // javac inserts a synthetic constructor for anonymous classes, and jacoco tends to mark
+      // these as covered in some cases, leading to flaky behavior.  We work around that by
+      // collecting the coverage count for each method in each class, omitting the default
+      // constructor for anonymous classes.  Anonymous classes are identified by their name,
+      // which we expect to be of the form 'Something$1'.  Jacoco names default constructors
+      // '<init>', so we filter based on that.
+      def isAnonymous = { c -> c.@name ==~ /.*\$\d+/ }
+      def methodFilter = isAnonymous(cls) ? { m -> m.@name != '<init>' } : { true }
+
+      def matchedMethods = cls.method.findAll(methodFilter)
+      if (isAnonymous(cls) && matchedMethods.isEmpty()) {
+        // Ignore anonymous classes that only have a constructor. This will avoid tripping for
+        // things like TypeLiteral and Clazz.
+        if (cls.@name in legacyClassesWithoutCoverage) {
+          return 'Please remove ' + cls.@name + ' from the legacyClassesWithoutCoverage list' \
+              + ', this check does not apply for constructor-only anonymous classes.'
+        } else {
+          return null
+        }
+      }
+
+      def covered = matchedMethods.collect { m ->
+        m.counter.find({ c -> c.@type == 'INSTRUCTION' }).@covered.toInteger()}.sum(0)
+
+      if (cls.@name in legacyClassesWithoutCoverage) {
+        if (covered != 0) {
+          return 'Thanks for adding the first test coverage to: ' + cls.@name \
+              + ' please remove it from the legacyClassesWithoutCoverage list'
+        }
+      } else if (covered == 0) {
+        return 'Test coverage missing for ' + cls.@name
+      }
+      return null
+    }.findAll()  // Filter nulls.
+    if (!coverageErrors.isEmpty()) {
+      throw new GradleException(coverageErrors.join('\n'))
+    }
+  }
+
+  @TaskAction
+  def analyze() {
+    def parser = new XmlSlurper()
+    parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
+    // Avoid trying to load the DTD for the XML document, which does not exist.
+    parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
+
+    def coverageReport = parser.parse(coverageReportFile)
+
+    checkGlobalCoverage(coverageReport.counter)
+    checkClassCoverage(coverageReport)
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftEntitiesPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftEntitiesPlugin.groovy b/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftEntitiesPlugin.groovy
new file mode 100644
index 0000000..31934f5
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftEntitiesPlugin.groovy
@@ -0,0 +1,113 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.build
+
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.file.FileTree
+import org.gradle.api.tasks.compile.JavaCompile
+
+class ThriftEntitiesPlugin implements Plugin<Project>  {
+  @Override
+  void apply(Project project) {
+
+    project.configure(project) {
+      apply plugin: ThriftPlugin
+
+      extensions.create('thriftEntities', ThriftEntitiesPluginExtension, project)
+
+      configurations.create('thriftEntitiesCompile')
+      configurations.thriftEntitiesCompile.extendsFrom(configurations.thriftRuntime)
+
+      afterEvaluate {
+        dependencies {
+          thriftEntitiesCompile "com.google.code.gson:gson:${thriftEntities.gsonRev}"
+          thriftEntitiesCompile "com.google.guava:guava:${thriftEntities.guavaRev}"
+        }
+      }
+      task('generateThriftEntitiesJava') {
+        inputs.files {thriftEntities.inputFiles}
+        outputs.dir {thriftEntities.genJavaDir}
+        doLast {
+          thriftEntities.genJavaDir.exists() || thriftEntities.genJavaDir.mkdirs()
+          thriftEntities.inputFiles.each { File file ->
+            exec {
+              commandLine thriftEntities.python,
+                  thriftEntities.codeGenerator,
+                  file.path,
+                  thriftEntities.genJavaDir,
+                  thriftEntities.genResourcesDir
+            }
+          }
+        }
+      }
+
+      task('classesThriftEntities', type: JavaCompile) {
+        source files(generateThriftEntitiesJava)
+        classpath = configurations.thriftRuntime + configurations.thriftEntitiesCompile
+        destinationDir = file(thriftEntities.genClassesDir)
+        options.warnings = false
+      }
+
+      configurations.create('thriftEntitiesRuntime')
+      configurations.thriftEntitiesRuntime.extendsFrom(configurations.thriftEntitiesCompile)
+      dependencies {
+        thriftEntitiesRuntime files(classesThriftEntities)
+      }
+      configurations.compile.extendsFrom(configurations.thriftEntitiesRuntime)
+      sourceSets.main {
+        output.dir(classesThriftEntities)
+        output.dir(thriftEntities.genResourcesDir, builtBy: 'generateThriftEntitiesJava')
+      }
+    }
+  }
+}
+
+class ThriftEntitiesPluginExtension {
+  def python = 'python2.7'
+  File genClassesDir
+  File genResourcesDir
+  File genJavaDir
+  FileTree inputFiles
+  def codeGenerator
+
+  String gsonRev
+  def getGsonRev() {
+    if (gsonRev == null) {
+      throw new GradleException('thriftEntities.gsonRev is required.')
+    } else {
+      return gsonRev
+    }
+  }
+
+  String guavaRev
+  def getGuavaRev() {
+    if (guavaRev == null) {
+      throw new GradleException('thriftEntities.guavaRev is required.')
+    } else {
+      return guavaRev
+    }
+  }
+
+  ThriftEntitiesPluginExtension(Project project) {
+    genClassesDir = project.file("${project.buildDir}/thriftEntities/classes")
+    genResourcesDir = project.file("${project.buildDir}/thriftEntities/gen-resources")
+    genJavaDir = project.file("${project.buildDir}/thriftEntities/gen-java")
+    inputFiles = project.fileTree("src/main/thrift").matching {
+      include "**/*.thrift"
+    }
+    codeGenerator = "${project.rootDir}/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py"
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftPlugin.groovy b/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftPlugin.groovy
new file mode 100644
index 0000000..e6114cf
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/aurora/build/ThriftPlugin.groovy
@@ -0,0 +1,127 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.build
+
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.file.FileTree
+import org.gradle.api.tasks.compile.JavaCompile
+
+class ThriftPlugin implements Plugin<Project> {
+  @Override
+  void apply(Project project) {
+    project.configure(project) {
+      apply plugin: 'java'
+
+      extensions.create('thrift', ThriftPluginExtension, project)
+
+      configurations.create('thriftCompile')
+      afterEvaluate {
+        dependencies {
+          thriftCompile "org.apache.thrift:libthrift:${thrift.version}"
+        }
+      }
+
+      task('generateThriftJava') {
+        inputs.files {thrift.inputFiles}
+        outputs.dir {thrift.genJavaDir}
+        doLast {
+          thrift.genJavaDir.exists() || thrift.genJavaDir.mkdirs()
+          thrift.inputFiles.each { File file ->
+            exec {
+              commandLine thrift.wrapperPath, thrift.version,
+                  '--gen', 'java:hashcode,private-members',
+                  '-out', thrift.genJavaDir.path,
+                  file.path
+            }
+          }
+        }
+      }
+
+      task('generateThriftResources') {
+        inputs.files {thrift.inputFiles}
+        outputs.dir {thrift.genResourcesDir}
+        doLast {
+          def dest = file("${thrift.genResourcesDir}/${thrift.resourcePrefix}")
+          dest.exists() || dest.mkdirs()
+          thrift.inputFiles.each { File file ->
+            exec {
+              commandLine thrift.wrapperPath, thrift.version,
+                  '--gen', 'js:jquery',
+                  '-out', dest.path, file.path
+            }
+          }
+        }
+      }
+
+      task('classesThrift', type: JavaCompile) {
+        source files(generateThriftJava)
+        classpath = configurations.thriftCompile
+        destinationDir = file(thrift.genClassesDir)
+        options.warnings = false
+      }
+
+      configurations.create('thriftRuntime')
+      configurations.thriftRuntime.extendsFrom(configurations.thriftCompile)
+      configurations.compile.extendsFrom(configurations.thriftRuntime)
+      dependencies {
+        thriftRuntime files(classesThrift)
+      }
+
+      sourceSets.main {
+        output.dir(classesThrift)
+        output.dir(generateThriftResources)
+      }
+    }
+  }
+}
+
+class ThriftPluginExtension {
+  def wrapperPath
+  File genResourcesDir
+  File genJavaDir
+  File genClassesDir
+  FileTree inputFiles
+
+  String version
+  String getVersion() {
+    if (version == null) {
+      throw new GradleException('thrift.version is required.')
+    } else {
+      return version
+    }
+  }
+
+  String resourcePrefix
+
+  /* Classpath prefix for generated resources. */
+  String getResourcesPrefix() {
+    if (resourcePrefix == null) {
+      throw new GradleException('thrift.resourcePrefix is required.')
+    } else {
+      return resourcePrefix
+    }
+  }
+
+  ThriftPluginExtension(Project project) {
+    wrapperPath = "${project.rootDir}/build-support/thrift/thriftw"
+    genResourcesDir = project.file("${project.buildDir}/thrift/gen-resources")
+    genJavaDir = project.file("${project.buildDir}/thrift/gen-java")
+    genClassesDir = project.file("${project.buildDir}/thrift/classes")
+    inputFiles = project.fileTree("src/main/thrift").matching {
+      include "**/*.thrift"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/gradle/wrapper/gradle-wrapper.properties
----------------------------------------------------------------------
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b043002..9cfd8b6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Nov 13 09:01:57 PST 2014
+#Thu Nov 13 11:02:51 PST 2014
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index 3e9cbfe..6180227 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,15 @@
-include 'buildSrc'
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+rootProject.name = 'aurora'
+include 'api', 'buildSrc'

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
index 4b92815..022b9f4 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
@@ -110,6 +110,17 @@ public class JettyServerModule extends AbstractModule {
       PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName(),
       PROPERTY_CONTAINER_RESPONSE_FILTERS, GZIPContentEncodingFilter.class.getName());
 
+  private static final String ENTITIES_HELP_ROOT = Resource
+      .newClassPathResource("org/apache/aurora/scheduler/storage/entities/help")
+      .toString();
+  private static final String API_CLIENT_ROOT = Resource
+      .newClassPathResource("org/apache/aurora/scheduler/gen/client")
+      .toString();
+  private static final String STATIC_ASSETS_ROOT = Resource
+      .newClassPathResource("scheduler/assets/index.html")
+      .toString()
+      .replace("assets/index.html", "");
+
   @Override
   protected void configure() {
     bind(Runnable.class)
@@ -162,7 +173,6 @@ public class JettyServerModule extends AbstractModule {
     private static final Map<String, String> REGEX_REWRITE_RULES =
         ImmutableMap.<String, String>builder()
             .put("/(?:index.html)?", "/assets/index.html")
-            .put("/apibeta/help/(.*)?", "/assets/org/apache/aurora/scheduler/storage/entities/$1")
             .put("/graphview(?:/index.html)?", "/assets/graphview/graphview.html")
             .put("/graphview/(.*)", "/assets/graphview/$1")
             .put("/(?:scheduler|updates)(?:/.*)?", "/assets/scheduler/index.html")
@@ -186,6 +196,16 @@ public class JettyServerModule extends AbstractModule {
       return rewrites;
     }
 
+    @Singleton
+    static class ApiHelpResourceServlet extends DefaultServlet {
+      // Subclass to allow extra instance of DefaultServlet.
+    }
+
+    @Singleton
+    static class ApiClientServlet extends DefaultServlet {
+      // Subclass to allow extra instance of DefaultServlet.
+    }
+
     @Override
     public LocalService launch() throws LaunchException {
       // N.B. we explicitly disable the resource cache here due to a bug serving content out of the
@@ -249,9 +269,23 @@ public class JettyServerModule extends AbstractModule {
               bind(DefaultServlet.class).in(Singleton.class);
               serve("/assets*")
                   .with(DefaultServlet.class, ImmutableMap.of(
-                      "resourceBase", Resource.newClassPathResource("scheduler").toString(),
+                      "resourceBase", STATIC_ASSETS_ROOT,
                       "dirAllowed", "false"));
 
+              serve("/apihelp/*")
+                  .with(ApiHelpResourceServlet.class, ImmutableMap.<String, String>builder()
+                      .put("resourceBase", ENTITIES_HELP_ROOT)
+                      .put("pathInfoOnly", "true")
+                      .put("dirAllowed", "false")
+                      .build());
+
+              serve("/apiclient/*")
+                  .with(ApiClientServlet.class, ImmutableMap.<String, String>builder()
+                      .put("resourceBase", API_CLIENT_ROOT)
+                      .put("pathInfoOnly", "true")
+                      .put("dirAllowed", "false")
+                      .build());
+
               bind(GuiceContainer.class).in(Singleton.class);
               registerJerseyEndpoint("/apibeta", ApiBeta.class);
               registerJerseyEndpoint("/cron", Cron.class);

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java b/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
index c072010..53ea03b 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
@@ -168,6 +168,6 @@ public class ApiBeta {
   @GET
   @Produces(MediaType.TEXT_HTML)
   public Response getIndex() {
-    return Response.seeOther(URI.create("/apibeta/help/index.html")).build();
+    return Response.seeOther(URI.create("/apihelp/index.html")).build();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/admin/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/admin/BUILD b/src/main/python/apache/aurora/admin/BUILD
index 9441e12..f874264 100644
--- a/src/main/python/apache/aurora/admin/BUILD
+++ b/src/main/python/apache/aurora/admin/BUILD
@@ -20,7 +20,7 @@ python_library(
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.quantity',
     'src/main/python/apache/aurora/client:api',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/client/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/client/BUILD b/src/main/python/apache/aurora/client/BUILD
index 48566d9..2a66825 100644
--- a/src/main/python/apache/aurora/client/BUILD
+++ b/src/main/python/apache/aurora/client/BUILD
@@ -28,7 +28,7 @@ python_library(
   dependencies = [
     '3rdparty/python:twitter.common.app',
     '3rdparty/python:twitter.common.log',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -50,7 +50,7 @@ python_library(
     '3rdparty/python:twitter.common.app',
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/config',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/client/api/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/client/api/BUILD b/src/main/python/apache/aurora/client/api/BUILD
index 6d2a1bf..8b0da67 100644
--- a/src/main/python/apache/aurora/client/api/BUILD
+++ b/src/main/python/apache/aurora/client/api/BUILD
@@ -23,7 +23,7 @@ python_library(
     '3rdparty/python:twitter.common.lang',
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/common',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -36,7 +36,7 @@ python_library(
     'src/main/python/apache/thermos/config:schema',
     'src/main/python/apache/aurora/common:cluster',
     'src/main/python/apache/aurora/config:schema',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -58,7 +58,7 @@ python_library(
     ':task_util',
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.quantity',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -69,7 +69,7 @@ python_library(
     ':instance_watcher',
     ':updater_util',
     '3rdparty/python:twitter.common.log',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -84,7 +84,7 @@ python_library(
     'src/main/python/apache/aurora/common/auth',
     'src/main/python/apache/aurora/common:cluster',
     'src/main/python/apache/aurora/common:transport',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -115,7 +115,7 @@ python_library(
     ':scheduler_mux',
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/client:base',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -129,7 +129,7 @@ python_library(
     '3rdparty/python:twitter.common.lang',
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/common:http_signaler',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -139,7 +139,7 @@ python_library(
   dependencies = [
     ':scheduler_client',
     '3rdparty/python:twitter.common.log',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -151,7 +151,7 @@ python_library(
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/client:base',
     'src/main/python/apache/aurora/common',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -166,7 +166,7 @@ python_library(
     ':quota_check',
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/client:base',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/client/cli/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/client/cli/BUILD b/src/main/python/apache/aurora/client/cli/BUILD
index e6627a8..8d34bf7 100644
--- a/src/main/python/apache/aurora/client/cli/BUILD
+++ b/src/main/python/apache/aurora/client/cli/BUILD
@@ -76,6 +76,6 @@ python_library(
     'src/main/python/apache/aurora/client:factory',
     'src/main/python/apache/aurora/client:options',
     'src/main/python/apache/aurora/common',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ],
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/client/commands/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/client/commands/BUILD b/src/main/python/apache/aurora/client/commands/BUILD
index d146015..f256483 100644
--- a/src/main/python/apache/aurora/client/commands/BUILD
+++ b/src/main/python/apache/aurora/client/commands/BUILD
@@ -33,7 +33,7 @@ python_library(
     'src/main/python/apache/aurora/client/api',
     'src/main/python/apache/aurora/client:base',
     'src/main/python/apache/aurora/common:clusters',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -67,7 +67,7 @@ python_library(
     'src/main/python/apache/aurora/client:factory',
     'src/main/python/apache/aurora/client:options',
     'src/main/python/apache/aurora/common',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/client/hooks/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/client/hooks/BUILD b/src/main/python/apache/aurora/client/hooks/BUILD
index f46cf65..49d73df 100644
--- a/src/main/python/apache/aurora/client/hooks/BUILD
+++ b/src/main/python/apache/aurora/client/hooks/BUILD
@@ -19,6 +19,6 @@ python_library(
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/client:api',
     'src/main/python/apache/aurora/common:aurora_job_key',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/common/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/common/BUILD b/src/main/python/apache/aurora/common/BUILD
index 02ec17c..2149688 100644
--- a/src/main/python/apache/aurora/common/BUILD
+++ b/src/main/python/apache/aurora/common/BUILD
@@ -19,7 +19,7 @@ python_library(
   sources = ['aurora_job_key.py'],
   dependencies = [
     '3rdparty/python:twitter.common.lang',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )
 
@@ -88,7 +88,7 @@ python_library(
     'src/main/python/apache/aurora/common/auth',
 
     # covering dependency on gen.*
-    'src/main/thrift/org/apache/aurora/gen:py-thrift-packaged',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift-packaged',
   ],
   provides = setup_py(
     name = 'apache.aurora.common',

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/common/auth/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/common/auth/BUILD b/src/main/python/apache/aurora/common/auth/BUILD
index c26d117..9664846 100644
--- a/src/main/python/apache/aurora/common/auth/BUILD
+++ b/src/main/python/apache/aurora/common/auth/BUILD
@@ -18,6 +18,6 @@ python_library(
   dependencies = [
     '3rdparty/python:twitter.common.lang',
     '3rdparty/python:twitter.common.log',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/config/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/config/BUILD b/src/main/python/apache/aurora/config/BUILD
index fa40ebd..0a3a93f 100644
--- a/src/main/python/apache/aurora/config/BUILD
+++ b/src/main/python/apache/aurora/config/BUILD
@@ -35,7 +35,7 @@ python_library(
     '3rdparty/python:twitter.common.lang',
     'src/main/python/apache/aurora/common',
     'src/main/python/apache/aurora/config/schema',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ],
 
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/config/schema/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/config/schema/BUILD b/src/main/python/apache/aurora/config/schema/BUILD
index 157c141..171f42a 100644
--- a/src/main/python/apache/aurora/config/schema/BUILD
+++ b/src/main/python/apache/aurora/config/schema/BUILD
@@ -18,6 +18,6 @@ python_library(
   dependencies = [
     '3rdparty/python:pystachio',
     'src/main/python/apache/thermos/config:schema',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/executor/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/BUILD b/src/main/python/apache/aurora/executor/BUILD
index ca4193d..3a2d4f8 100644
--- a/src/main/python/apache/aurora/executor/BUILD
+++ b/src/main/python/apache/aurora/executor/BUILD
@@ -133,8 +133,8 @@ python_library(
     'src/main/python/apache/thermos/monitoring:garbage',
     'src/main/python/apache/aurora/config:schema',
     'src/main/python/apache/aurora/executor/common:sandbox',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/executor/common/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/BUILD b/src/main/python/apache/aurora/executor/common/BUILD
index d33e14b..142ec0d 100644
--- a/src/main/python/apache/aurora/executor/common/BUILD
+++ b/src/main/python/apache/aurora/executor/common/BUILD
@@ -96,6 +96,6 @@ python_library(
     '3rdparty/python:twitter.common.log',
     'src/main/python/apache/aurora/config',
     'src/main/python/apache/aurora/config/schema',
-    'src/main/thrift/org/apache/aurora/gen:py-thrift',
+    'api/src/main/thrift/org/apache/aurora/gen:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py b/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py
index d6bb5a1..ca2581c 100644
--- a/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py
+++ b/src/main/python/apache/aurora/tools/java/thrift_wrapper_codegen.py
@@ -489,12 +489,12 @@ def parse_structs(thrift_defs):
   for s in re.finditer(STRUCT_RE, thrift_defs, flags=re.MULTILINE):
     if s.group('kind') == 'enum':
       struct = EnumType(s.group('name'),
-                        namespaces['java'],
+                        namespaces.get('java', ''),
                         parse_values(s.group('body')),
                         s.group('doc'))
     else:
       struct = StructType(s.group('name'),
-                          namespaces['java'],
+                          namespaces.get('java', ''),
                           s.group('kind'),
                           parse_fields(s.group('body')),
                           s.group('doc'))
@@ -633,6 +633,10 @@ if __name__ == '__main__':
   with open(thrift_file) as f:
     # Load all structs found in the thrift file.
     file_contents = f.read()
+    services = parse_services(file_contents)
+    if not services:
+      log('Skipping doc generation for %s since there are no services.' % thrift_file)
+      sys.exit(0)
     structs = parse_structs(file_contents)
 
     package_dir = os.path.join(code_output_dir, PACKAGE_NAME.replace('.', os.path.sep))
@@ -648,8 +652,7 @@ if __name__ == '__main__':
         code = generate_java(struct)
         code.dump(f)
 
-    services = parse_services(file_contents)
-    resource_dir = os.path.join(resource_output_dir, PACKAGE_NAME.replace('.', os.path.sep))
+    resource_dir = os.path.join(resource_output_dir, PACKAGE_NAME.replace('.', os.path.sep), 'help')
     if not os.path.isdir(resource_dir):
       os.makedirs(resource_dir)
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/bin/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/bin/BUILD b/src/main/python/apache/thermos/bin/BUILD
index 34e2b3f..a1d6e52 100644
--- a/src/main/python/apache/thermos/bin/BUILD
+++ b/src/main/python/apache/thermos/bin/BUILD
@@ -19,7 +19,7 @@ python_binary(
     '3rdparty/python:twitter.common.app',
     '3rdparty/python:twitter.common.recordio',
     'src/main/python/apache/thermos/common',
-    'src/main/thrift/org/apache/thermos:py-thrift'
+    'api/src/main/thrift/org/apache/thermos:py-thrift'
   ]
 )
 
@@ -33,6 +33,6 @@ python_binary(
     'src/main/python/apache/thermos/config:schema',
     'src/main/python/apache/thermos/core',
     'src/main/python/apache/thermos/monitoring',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ],
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/common/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/common/BUILD b/src/main/python/apache/thermos/common/BUILD
index 918800b..24d7b6e 100644
--- a/src/main/python/apache/thermos/common/BUILD
+++ b/src/main/python/apache/thermos/common/BUILD
@@ -20,7 +20,7 @@ python_library(
   dependencies = [
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.recordio',
-    'src/main/thrift/org/apache/thermos:py-thrift'
+    'api/src/main/thrift/org/apache/thermos:py-thrift'
   ]
 )
 
@@ -39,7 +39,7 @@ python_library(
   sources = ['options.py'],
   dependencies = [
     '3rdparty/python:pystachio',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/core/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/core/BUILD b/src/main/python/apache/thermos/core/BUILD
index f362acd..efb68e8 100644
--- a/src/main/python/apache/thermos/core/BUILD
+++ b/src/main/python/apache/thermos/core/BUILD
@@ -25,7 +25,7 @@ python_library(
     '3rdparty/python:twitter.common.recordio',
     'src/main/python/apache/thermos/common:ckpt',
     'src/main/python/apache/thermos/common:path',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 
@@ -37,7 +37,7 @@ python_library(
     '3rdparty/python:twitter.common.recordio',
     'src/main/python/apache/thermos/common:ckpt',
     'src/main/python/apache/thermos/common:path',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 
@@ -47,7 +47,7 @@ python_library(
   dependencies = [
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.recordio',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 
@@ -60,7 +60,7 @@ python_library(
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.quantity',
     '3rdparty/python:twitter.common.recordio',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 
@@ -80,7 +80,7 @@ python_library(
     'src/main/python/apache/thermos/common:path',
     'src/main/python/apache/thermos/common:planner',
     'src/main/python/apache/thermos/config:schema',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 
@@ -93,7 +93,7 @@ python_library(
     # covering libs
     'src/main/python/apache/thermos/common',
     'src/main/python/apache/thermos/config',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ],
   provides = setup_py(
     name = 'apache.thermos.core',

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/monitoring/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/monitoring/BUILD b/src/main/python/apache/thermos/monitoring/BUILD
index 0dad47e..33259c8 100644
--- a/src/main/python/apache/thermos/monitoring/BUILD
+++ b/src/main/python/apache/thermos/monitoring/BUILD
@@ -42,7 +42,7 @@ python_library(
     '3rdparty/python:twitter.common.log',
     '3rdparty/python:twitter.common.recordio',
     'src/main/python/apache/thermos/common:ckpt',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/observer/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/observer/BUILD b/src/main/python/apache/thermos/observer/BUILD
index b07db90..ee65f3a 100644
--- a/src/main/python/apache/thermos/observer/BUILD
+++ b/src/main/python/apache/thermos/observer/BUILD
@@ -40,7 +40,7 @@ python_library(
     'src/main/python/apache/thermos/monitoring:monitor',
     'src/main/python/apache/thermos/monitoring:process',
     'src/main/python/apache/thermos/monitoring:resource',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/python/apache/thermos/testing/BUILD
----------------------------------------------------------------------
diff --git a/src/main/python/apache/thermos/testing/BUILD b/src/main/python/apache/thermos/testing/BUILD
index b96c166..8b5f6dc 100644
--- a/src/main/python/apache/thermos/testing/BUILD
+++ b/src/main/python/apache/thermos/testing/BUILD
@@ -23,6 +23,6 @@ python_library(
     'src/main/python/apache/thermos/common:path',
     'src/main/python/apache/thermos/config',
     'src/main/python/apache/thermos/core',
-    'src/main/thrift/org/apache/thermos:py-thrift',
+    'api/src/main/thrift/org/apache/thermos:py-thrift',
   ]
 )

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/resources/scheduler/assets/scheduler/index.html
----------------------------------------------------------------------
diff --git a/src/main/resources/scheduler/assets/scheduler/index.html b/src/main/resources/scheduler/assets/scheduler/index.html
index f4ca071..383ca43 100644
--- a/src/main/resources/scheduler/assets/scheduler/index.html
+++ b/src/main/resources/scheduler/assets/scheduler/index.html
@@ -41,8 +41,8 @@
 
 <!-- Thrift -->
 <script src='/assets/js/thrift.js'></script>
-<script src='/assets/js/api_types.js'></script>
-<script src='/assets/js/ReadOnlyScheduler.js'></script>
+<script src='/apiclient/api_types.js'></script>
+<script src='/apiclient/ReadOnlyScheduler.js'></script>
 
 <!-- Angular -->
 <script src='/assets/bower_components/angular/angular.js'></script>

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/aurora/gen/BUILD
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/aurora/gen/BUILD b/src/main/thrift/org/apache/aurora/gen/BUILD
deleted file mode 100644
index fe3f83b..0000000
--- a/src/main/thrift/org/apache/aurora/gen/BUILD
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-
-TEST_DATA = globs('*test.thrift')
-
-python_thrift_library(
-  name = 'py-thrift',
-  sources = [
-    'api.thrift',
-    'internal_rpc.thrift',
-  ],
-)
-
-python_thrift_library(
-  name = 'py-thrift-test',
-  sources = TEST_DATA,
-)
-
-python_thrift_library(
-  name = 'py-thrift-storage',
-  sources = ['storage.thrift'],
-  dependencies = [
-    ':py-thrift',
-  ],
-)
-
-python_library(
-  name = 'py-thrift-packaged',
-  dependencies = [
-    ':py-thrift',
-    ':py-thrift-test',
-    ':py-thrift-storage',
-  ],
-  provides = setup_py(
-    name = 'apache.gen.aurora',
-    version = open(os.path.join(get_buildroot(), '.auroraversion')).read().strip().upper(),
-    description = 'Autogenerated Aurora thrift schemas.',
-  )
-)

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/aurora/gen/api.thrift
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/aurora/gen/api.thrift b/src/main/thrift/org/apache/aurora/gen/api.thrift
deleted file mode 100644
index b91fca9..0000000
--- a/src/main/thrift/org/apache/aurora/gen/api.thrift
+++ /dev/null
@@ -1,1117 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace java org.apache.aurora.gen
-namespace py gen.apache.aurora.api
-
-// Thrift interface definition for the aurora scheduler.
-
-/*
- * TODO(wfarner): It would be nice if we could put some HTML tags here, regex doesn't handle it though.
- * The result of an API operation.  A result may only be specified when this is OK.
- */
-enum ResponseCode {
-  INVALID_REQUEST = 0,
-  OK              = 1,
-  ERROR           = 2,
-  WARNING         = 3,
-  AUTH_FAILED     = 4,
-  /** Raised when a Lock-protected operation failed due to lock validation. */
-  LOCK_ERROR      = 5,
-  /** Raised when a scheduler is transiently unavailable and later retry is recommended. */
-  ERROR_TRANSIENT = 6
-}
-
-const i32 THRIFT_API_VERSION = 3
-
-struct APIVersion {
-  1: required i32 major
-}
-
-// Scheduler Thrift API Version. Increment this when breaking backwards compatibility.
-const APIVersion CURRENT_API_VERSION = {'major': THRIFT_API_VERSION}
-
-// Aurora executor framework name.
-const string AURORA_EXECUTOR_NAME = 'AuroraExecutor'
-
-// TODO(maxim): Remove in 0.7.0. (AURORA-749)
-struct Identity {
-  1: string role
-  2: string user
-}
-
-struct SessionKey {
-  /**
-   * The name of the authentication mechanism, which instructs the server how to interpret the data
-   * field.
-   */
-  4: optional string mechanism
-  /** A blob of data that the server may use for authentication. */
-  5: optional binary data
-}
-
-struct ResourceAggregate {
-  /** Number of CPU cores allotted. */
-  1: double numCpus
-  /** Megabytes of RAM allotted. */
-  2: i64 ramMb
-  /** Megabytes of disk space allotted. */
-  3: i64 diskMb
-}
-
-/** A single host attribute. */
-struct Attribute {
-  1: string name
-  2: set<string> values
-}
-
-enum MaintenanceMode {
-  NONE      = 1,
-  SCHEDULED = 2,
-  DRAINING  = 3,
-  DRAINED   = 4
-}
-
-/** The attributes assigned to a host. */
-struct HostAttributes {
-  1: string          host
-  2: set<Attribute>  attributes
-  3: optional MaintenanceMode mode
-  4: optional string slaveId
-}
-
-/**
- * A constraint that specifies an explicit set of values, at least one of which must be present
- * on a host for a task to be scheduled there.
- */
-struct ValueConstraint {
-  /** If true, treat this as a 'not' - to avoid specific values. */
-  1: bool negated
-  2: set<string> values
-}
-
-/**
- * A constraint the specifies the maximum number of active tasks on a host with a matching
- * attribute that may be scheduled simultaneously.
- */
-struct LimitConstraint {
-  1: i32 limit
-}
-
-/** Types of constraints that may be applied to a task. */
-union TaskConstraint {
-  1: ValueConstraint value
-  2: LimitConstraint limit
-}
-
-/** A constraint that defines whether a task may be scheduled on a host. */
-struct Constraint {
-  /** Mesos slave attribute that the constraint is matched against. */
-  1: string name
-  2: TaskConstraint constraint
-}
-
-struct Package {
-  1: string role
-  2: string name
-  3: i32 version
-}
-
-/** Arbitrary key-value metadata to be included into TaskConfig. */
-struct Metadata {
-  1: string key
-  2: string value
-}
-
-/** A unique identifier for a Job. */
-struct JobKey {
-  /** User role (Unix service account), for example "mesos" */
-  1: string role
-  /** Environment, for example "devel" */
-  2: string environment
-  /** Name, for example "labrat" */
-  3: string name
-}
-
-/** A unique lock key. */
-union LockKey {
-  1: JobKey job
-}
-
-/** A generic lock struct to facilitate context specific resource/operation serialization. */
-struct Lock {
-  /** ID of the lock - unique per storage */
-  1: LockKey key
-  /** UUID - facilitating soft lock authorization */
-  2: string token
-  /** Lock creator */
-  3: string user
-  /** Lock creation timestamp in milliseconds */
-  4: i64 timestampMs
-  /** Optional message to record with the lock */
-  5: optional string message
-}
-
-/** Defines the required lock validation level. */
-enum LockValidation {
-  /** The lock must be valid in order to be released. */
-  CHECKED   = 0
-  /** The lock will be released without validation (aka "force release"). */
-  UNCHECKED = 1
-}
-
-/** A unique identifier for the active task within a job. */
-struct InstanceKey {
-  /** Key identifying the job. */
-  1: JobKey jobKey
-  /** Unique instance ID for the active task in a job. */
-  2: i32 instanceId
-}
-
-struct ExecutorConfig {
-  /** Name identifying the Executor. */
-  1: string name
-  /** Executor configuration data. */
-  2: string data
-}
-
-/** Description of the tasks contained within a job. */
-struct TaskConfig {
- /** Job task belongs to. */
- 28: JobKey job
- // TODO(maxim): Remove in 0.7.0. (AURORA-749)
- /** contains the role component of JobKey */
- 17: Identity owner
- // TODO(maxim): Remove in 0.7.0. (AURORA-749)
- /** contains the environment component of JobKey */
- 26: string environment
- // TODO(maxim): Remove in 0.7.0. (AURORA-749)
- /** contains the name component of JobKey */
-  3: string jobName
-  7: bool isService
-  8: double numCpus
-  9: i64 ramMb
- 10: i64 diskMb
- 11: i32 priority
- 13: i32 maxTaskFailures
- /** Whether this is a production task, which can preempt. */
- 18: optional bool production
-
- 20: set<Constraint> constraints
- /** a list of named ports this task requests */
- 21: set<string> requestedPorts
-
- /**
-  * Custom links to include when displaying this task on the scheduler dashboard. Keys are anchor
-  * text, values are URLs. Wildcards are supported for dynamic link crafting based on host, ports,
-  * instance, etc.
-  */
- 22: optional map<string, string> taskLinks
- 23: optional string contactEmail
- /** Executor configuration */
- 25: optional ExecutorConfig executorConfig
- /** Used to display additional details in the UI. */
- 27: optional set<Metadata> metadata
-}
-
-/** Defines the policy for launching a new cron job when one is already running. */
-enum CronCollisionPolicy {
-  /** Kills the existing job with the colliding name, and runs the new cron job. */
-  KILL_EXISTING = 0,
-  /** Cancels execution of the new job, leaving the running job in tact. */
-  CANCEL_NEW    = 1,
-  /**
-   * DEPRECATED. For existing jobs, treated the same as CANCEL_NEW.
-   * createJob will reject jobs with this policy.
-   */
-  RUN_OVERLAP   = 2
-}
-
-/**
- * Description of an Aurora job. One task will be scheduled for each instance within the job.
- */
-struct JobConfiguration {
-  /**
-   * Key for this job. If not specified name, owner.role, and a reasonable default environment are
-   * used to construct it server-side.
-   */
-  9: JobKey key
-  // TODO(maxim): Remove in 0.7.0. (AURORA-749)
-  /** Owner of this job. */
-  7: Identity owner
-  /**
-   * If present, the job will be handled as a cron job with this crontab-syntax schedule.
-   */
-  4: string cronSchedule
-  /** Collision policy to use when handling overlapping cron runs.  Default is KILL_EXISTING. */
-  5: CronCollisionPolicy cronCollisionPolicy
-  /** Task configuration for this job. */
-  6: TaskConfig taskConfig
-  /**
-   * The number of instances in the job. Generated instance IDs for tasks will be in the range
-   * [0, instances).
-   */
-  8: i32 instanceCount
-}
-
-struct JobStats {
-  /** Number of tasks in active state for this job. */
-  1: i32 activeTaskCount
-  /** Number of tasks in finished state for this job. */
-  2: i32 finishedTaskCount
-  /** Number of failed tasks for this job. */
-  3: i32 failedTaskCount
-  /** Number of tasks in pending state for this job. */
-  4: i32 pendingTaskCount
-}
-
-struct JobSummary {
-  1: JobConfiguration job
-  2: JobStats stats
-  /** Timestamp of next cron run in ms since epoch, for a cron job */
-  3: optional i64 nextCronRunMs
-}
-
-/** A request to add the following instances to an existing job. Used by addInstances. */
-struct AddInstancesConfig {
-  1: JobKey key
-  2: TaskConfig taskConfig
-  3: set<i32> instanceIds
-}
-
-/** Closed range of integers. */
-struct Range {
-  1: i32 first
-  2: i32 last
-}
-
-struct ConfigGroup {
-  1: TaskConfig config
-  2: set<i32> instanceIds   // TODO(maxim): change it to use list<Range> instead.
-}
-
-struct ConfigSummary {
-  1: JobKey key
-  2: set<ConfigGroup> groups
-}
-
-struct PopulateJobResult {
-  // TODO(maxim): Remove populated field in 0.7.0. (AURORA-691)
-  1: set<TaskConfig> populatedDEPRECATED
-  2: TaskConfig taskConfig
-}
-
-struct GetQuotaResult {
-  /** Total allocated resource quota. */
-  1: ResourceAggregate quota
-  /** Resources consumed by production jobs. */
-  2: optional ResourceAggregate prodConsumption
-  /** Resources consumed by non-production jobs. */
-  3: optional ResourceAggregate nonProdConsumption
-}
-
-/** Wraps return results for the acquireLock API. */
-struct AcquireLockResult {
-  /** Acquired Lock instance. */
-  1: Lock lock
-}
-
-/** States that a task may be in. */
-enum ScheduleStatus {
-  // TODO(maxim): This state does not add much value. Consider dropping it completely.
-  /* Initial state for a task.  A task will remain in this state until it has been persisted. */
-  INIT             = 11,
-  /** The task will be rescheduled, but is being throttled for restarting too frequently. */
-  THROTTLED        = 16,
-  /** Task is awaiting assignment to a slave. */
-  PENDING          = 0,
-  /** Task has been assigned to a slave. */
-  ASSIGNED         = 9,
-  /** Slave has acknowledged receipt of task and is bootstrapping the task. */
-  STARTING         = 1,
-  /** The task is running on the slave. */
-  RUNNING          = 2,
-  /** The task terminated with an exit code of zero. */
-  FINISHED         = 3,
-  /** The task is being preempted by another task. */
-  PREEMPTING       = 13,
-  /** The task is being restarted in response to a user request. */
-  RESTARTING       = 12,
-  /** The task is being restarted in response to a host maintenance request. */
-  DRAINING         = 17,
-  /** The task terminated with a non-zero exit code. */
-  FAILED           = 4,
-  /** Execution of the task was terminated by the system. */
-  KILLED           = 5,
-  /** The task is being forcibly killed. */
-  KILLING          = 6,
-  /** A fault in the task environment has caused the system to believe the task no longer exists.
-   * This can happen, for example, when a slave process disappears.
-   */
-  LOST             = 7,
-  // TODO(maxim): Remove SANDBOX_DELETED in 0.7.0. (AURORA-832)
-  /** The task sandbox has been deleted by the executor. */
-  SANDBOX_DELETED  = 10
-}
-
-// States that a task may be in while still considered active.
-const set<ScheduleStatus> ACTIVE_STATES = [ScheduleStatus.ASSIGNED,
-                                           ScheduleStatus.DRAINING,
-                                           ScheduleStatus.KILLING,
-                                           ScheduleStatus.PENDING,
-                                           ScheduleStatus.PREEMPTING,
-                                           ScheduleStatus.RESTARTING
-                                           ScheduleStatus.RUNNING,
-                                           ScheduleStatus.STARTING,
-                                           ScheduleStatus.THROTTLED]
-
-// States that a task may be in while associated with a slave machine and non-terminal.
-const set<ScheduleStatus> SLAVE_ASSIGNED_STATES = [ScheduleStatus.ASSIGNED,
-                                                   ScheduleStatus.DRAINING,
-                                                   ScheduleStatus.KILLING,
-                                                   ScheduleStatus.PREEMPTING,
-                                                   ScheduleStatus.RESTARTING,
-                                                   ScheduleStatus.RUNNING,
-                                                   ScheduleStatus.STARTING]
-
-// States that a task may be in while in an active sandbox.
-const set<ScheduleStatus> LIVE_STATES = [ScheduleStatus.KILLING,
-                                         ScheduleStatus.PREEMPTING,
-                                         ScheduleStatus.RESTARTING,
-                                         ScheduleStatus.DRAINING,
-                                         ScheduleStatus.RUNNING]
-
-// States a completed task may be in.
-const set<ScheduleStatus> TERMINAL_STATES = [ScheduleStatus.FAILED,
-                                             ScheduleStatus.FINISHED,
-                                             ScheduleStatus.KILLED,
-                                             ScheduleStatus.LOST,
-                                             ScheduleStatus.SANDBOX_DELETED]
-
-// Regular expressions for matching valid identifiers for job path components. All expressions
-// below should accept and reject the same set of inputs.
-const string GOOD_IDENTIFIER_PATTERN = "^[\\w\\-\\.]+$"
-// JVM: Use with java.util.regex.Pattern#compile
-const string GOOD_IDENTIFIER_PATTERN_JVM = GOOD_IDENTIFIER_PATTERN
-// Python: Use with re.compile
-const string GOOD_IDENTIFIER_PATTERN_PYTHON = GOOD_IDENTIFIER_PATTERN
-
-/** Event marking a state transition within a task's lifecycle. */
-struct TaskEvent {
-  /** Epoch timestamp in milliseconds. */
-  1: i64 timestamp
-  /** New status of the task. */
-  2: ScheduleStatus status
-  /** Audit message that explains why a transition occurred. */
-  3: optional string message
-  /** Hostname of the scheduler machine that performed the event. */
-  4: optional string scheduler
-}
-
-/** A task assignment that is provided to an executor. */
-struct AssignedTask {
-  /** The mesos task ID for this task.  Guaranteed to be globally unique */
-  1: string taskId
-
-  /**
-   * The mesos slave ID that this task has been assigned to.
-   * This will not be populated for a PENDING task.
-   */
-  2: string slaveId
-
-  /**
-   * The name of the machine that this task has been assigned to.
-   * This will not be populated for a PENDING task.
-   */
-  3: string slaveHost
-
-  /** Information about how to run this task. */
-  4: TaskConfig task
-  /** Ports reserved on the machine while this task is running. */
-  5: map<string, i32> assignedPorts
-
-  /**
-   * The instance ID assigned to this task. Instance IDs must be unique and contiguous within a
-   * job, and will be in the range [0, N-1] (inclusive) for a job that has N instances.
-   */
-  6: i32 instanceId
-}
-
-/** A task that has been scheduled. */
-struct ScheduledTask {
-  /** The task that was scheduled. */
-  1: AssignedTask assignedTask
-  /** The current status of this task. */
-  2: ScheduleStatus status
-  /**
-   * The number of failures that this task has accumulated over the multi-generational history of
-   * this task.
-   */
-  3: i32 failureCount
-  /** State change history for this task. */
-  4: list<TaskEvent> taskEvents
-  /**
-   * The task ID of the previous generation of this task.  When a task is automatically rescheduled,
-   * a copy of the task is created and ancestor ID of the previous task's task ID.
-   */
-  5: string ancestorId
-}
-
-struct ScheduleStatusResult {
-  1: list<ScheduledTask> tasks
-}
-
-struct GetJobsResult {
-  1: set<JobConfiguration> configs
-}
-
-/**
- * Contains a set of restrictions on matching tasks where all restrictions must be met
- * (terms are AND'ed together).
- */
-struct TaskQuery {
-  // TODO(maxim): Remove in 0.7.0. (AURORA-749)
-  8: Identity owner
-  14: string role
-  9: string environment
-  2: string jobName
-  4: set<string> taskIds
-  5: set<ScheduleStatus> statuses
-  7: set<i32> instanceIds
-  10: set<string> slaveHosts
-  11: set<JobKey> jobKeys
-  12: i32 offset
-  13: i32 limit
-}
-
-struct HostStatus {
-  1: string host
-  2: MaintenanceMode mode
-}
-
-struct RoleSummary {
-  1: string role
-  2: i32 jobCount
-  3: i32 cronJobCount
-}
-
-struct Hosts {
-  1: set<string> hostNames
-}
-
-struct PendingReason {
-  1: string taskId
-  2: string reason
-}
-
-/** States that a job update may be in. */
-enum JobUpdateStatus {
-  /** Update is in progress. */
-  ROLLING_FORWARD = 0,
-
-  /** Update has failed and is being rolled back. */
-  ROLLING_BACK = 1,
-
-  /** Update has been paused while in progress. */
-  ROLL_FORWARD_PAUSED = 2,
-
-  /** Update has been paused during rollback. */
-  ROLL_BACK_PAUSED = 3,
-
-  /** Update has completed successfully. */
-  ROLLED_FORWARD = 4,
-
-  /** Update has failed and rolled back. */
-  ROLLED_BACK = 5,
-
-  /** Update was aborted. */
-  ABORTED = 6,
-
-  /** Unknown error during update. */
-  ERROR = 7
-
-  /**
-   * Update failed to complete.
-   * This can happen if failure thresholds are met while rolling forward, but rollback is disabled,
-   * or if failure thresholds are met when rolling back.
-   */
-  FAILED = 8
-}
-
-/** States the job update can be in while still considered active. */
-const set<JobUpdateStatus> ACTIVE_JOB_UPDATE_STATES = [JobUpdateStatus.ROLLING_FORWARD,
-                                                       JobUpdateStatus.ROLLING_BACK,
-                                                       JobUpdateStatus.ROLL_FORWARD_PAUSED,
-                                                       JobUpdateStatus.ROLL_BACK_PAUSED]
-
-/** Job update actions that can be applied to job instances. */
-enum JobUpdateAction {
-  /**
-   * An instance was moved to the target state successfully, and declared healthy if the desired
-   * state did not involve deleting the instance.
-   */
-  INSTANCE_UPDATED = 1,
-
-  /**
-   * An instance was rolled back because the job update did not succeed.  The instance was reverted
-   * to the original state prior to the job update, which means that the instance was removed if
-   * the update added instances to the job.
-   */
-  INSTANCE_ROLLED_BACK = 2,
-
-  /**
-   * An instance is being moved from the original state to the desired state.
-   */
-  INSTANCE_UPDATING = 3,
-
-  /**
-   * An instance is being moved from the desired state back to the original state, because the job
-   * update failed.
-   */
-  INSTANCE_ROLLING_BACK = 4,
-
-  /** An instance update was attempted but failed and was not rolled back. */
-  INSTANCE_UPDATE_FAILED = 5,
-
-  /** An instance rollback was attempted but failed. */
-  INSTANCE_ROLLBACK_FAILED = 6
-}
-
-/** Status of the coordinated update. Intended as a response to pulseJobUpdate RPC. */
-enum JobUpdatePulseStatus {
-  /**
-   *  Update is active (ACK).
-   */
-  OK = 1,
-
-  /**
-   * Update is paused and will not progress unless explicitly resumed (NACK).
-   */
-  PAUSED = 2,
-
-  /**
-   * Update has reached terminal state.
-   */
-  FINISHED = 3
-}
-
-/** Job update thresholds and limits. */
-struct JobUpdateSettings {
-  /** Max number of instances being updated at any given moment. */
-  1: i32 updateGroupSize
-
-  /** Max number of instance failures to tolerate before marking instance as FAILED. */
-  2: i32 maxPerInstanceFailures
-
-  /** Max number of FAILED instances to tolerate before terminating the update. */
-  3: i32 maxFailedInstances
-
-  /** Max time to wait until an instance reaches RUNNING state. */
-  4: i32 maxWaitToInstanceRunningMs
-
-  /** Min time to watch a RUNNING instance. */
-  5: i32 minWaitInInstanceRunningMs
-
-  /** If true, enables failed update rollback. */
-  6: bool rollbackOnFailure
-
-  /** Instance IDs to act on. All instances will be affected if this is not set. */
-  7: set<Range> updateOnlyTheseInstances
-
-  /**
-   * If true, use updateGroupSize as strict batching boundaries, and avoid proceeding to another
-   * batch until the preceding batch finishes updating.
-   */
-  8: bool waitForBatchCompletion
-
- /**
-  * If set, requires external calls to pulseJobUpdate RPC within the specified rate for the
-  * update to make progress. If no pulses received within specified interval the update will
-  * block. A blocked update is unable to continue but retains its current status. It may only get
-  * unblocked by a fresh pulseJobUpdate call.
-  */
-  9: i32 blockIfNoPulsesAfterMs
-}
-
-/** Event marking a state transition in job update lifecycle. */
-struct JobUpdateEvent {
-  /** Update status. */
-  1: JobUpdateStatus status
-
-  /** Epoch timestamp in milliseconds. */
-  2: i64 timestampMs
-
-  /** User who performed this event (if user-initiated). */
-  3: optional string user
-}
-
-/** Event marking a state transition in job instance update lifecycle. */
-struct JobInstanceUpdateEvent {
-  /** Job instance ID. */
-  1: i32 instanceId
-
-  /** Epoch timestamp in milliseconds. */
-  2: i64 timestampMs
-
-  /** Job update action taken on the instance. */
-  3: JobUpdateAction action
-}
-
-/** Maps instance IDs to TaskConfigs it. */
-struct InstanceTaskConfig {
-  /** A TaskConfig associated with instances. */
-  1: TaskConfig task
-
-  /** Instances associated with the TaskConfig. */
-  2: set<Range> instances
-}
-
-/** Current job update state including status and created/modified timestamps. */
-struct JobUpdateState {
-  /** Current status of the update. */
-  1: JobUpdateStatus status
-
-  /** Created timestamp in milliseconds. */
-  2: i64 createdTimestampMs
-
-  /** Last modified timestamp in milliseconds. */
-  3: i64 lastModifiedTimestampMs
-}
-
-/** Summary of the job update including job key, user and current state. */
-struct JobUpdateSummary {
-  /** Update ID. */
-  1: string updateId
-
-  /** Job key. */
-  2: JobKey jobKey
-
-  /** User initiated an update. */
-  3: string user
-
-  /** Current job update state. */
-  4: JobUpdateState state
-}
-
-/** Update configuration and setting details. */
-struct JobUpdateInstructions {
-  /** Actual InstanceId -> TaskConfig mapping when the update was requested. */
-  1: set<InstanceTaskConfig> initialState
-
-  /** Desired configuration when the update completes. */
-  2: InstanceTaskConfig desiredState
-
-  /** Update specific settings. */
-  3: JobUpdateSettings settings
-}
-
-/** Full definition of the job update. */
-struct JobUpdate {
-  /** Update summary. */
-  1: JobUpdateSummary summary
-
-  /** Update configuration. */
-  2: JobUpdateInstructions instructions
-}
-
-struct JobUpdateDetails {
-  /** Update definition. */
-  1: JobUpdate update
-
-  /** History for this update. */
-  2: list<JobUpdateEvent> updateEvents
-
-  /** History for the individual instances updated. */
-  3: list<JobInstanceUpdateEvent> instanceEvents
-}
-
-/** A request to update the following instances of an existing job. Used by startUpdate. */
-struct JobUpdateRequest {
-  /** Desired TaskConfig to apply. */
-  1: TaskConfig taskConfig
-
-  /** Desired number of instances of the task config. */
-  2: i32 instanceCount
-
-  /** Update settings and limits. */
-  3: JobUpdateSettings settings
-}
-
-/**
- * Contains a set of restrictions on matching job updates where all restrictions must be met
- * (terms are AND'ed together).
- */
-struct JobUpdateQuery {
-  /** Update ID. */
-  1: string updateId
-
-  /** Job role. */
-  2: string role
-
-  /** Job key. */
-  3: JobKey jobKey
-
-  /** User who created the update. */
-  4: string user
-
-  /** Set of update statuses. */
-  5: set<JobUpdateStatus> updateStatuses
-
-  /** Offset to serve data from. Used by pagination. */
-  6: i32 offset
-
-  /** Number or records to serve. Used by pagination. */
-  7: i32 limit
-}
-
-struct ListBackupsResult {
-  1: set<string> backups
-}
-
-struct StartMaintenanceResult {
-  1: set<HostStatus> statuses
-}
-
-struct DrainHostsResult {
-  1: set<HostStatus> statuses
-}
-
-struct QueryRecoveryResult {
-  1: set<ScheduledTask> tasks
-}
-
-struct MaintenanceStatusResult {
-  1: set<HostStatus> statuses
-}
-
-struct EndMaintenanceResult {
-  1: set<HostStatus> statuses
-}
-
-struct RoleSummaryResult {
-  1: set<RoleSummary> summaries
-}
-
-struct JobSummaryResult {
-  1: set<JobSummary> summaries
-}
-
-struct GetLocksResult {
-  1: set<Lock> locks
-}
-
-struct ConfigSummaryResult {
-  1: ConfigSummary summary
-}
-
-struct GetPendingReasonResult {
-  1: set<PendingReason> reasons
-}
-
-/** Result of the startUpdate call. */
-struct StartJobUpdateResult {
-  /** Job update ID. */
-  1: string updateId
-}
-
-/** Result of the getJobUpdateSummaries call. */
-struct GetJobUpdateSummariesResult {
-  1: list<JobUpdateSummary> updateSummaries
-}
-
-/** Result of the getJobUpdateDetails call. */
-struct GetJobUpdateDetailsResult {
-  1: JobUpdateDetails details
-}
-
-/** Result of the pulseJobUpdate call. */
-struct PulseJobUpdateResult {
-  1: JobUpdatePulseStatus status
-}
-
-/** Information about the scheduler. */
-struct ServerInfo {
-  1: string clusterName
-  2: i32 thriftAPIVersion
-  /** A url prefix for job container stats. */
-  3: string statsUrlPrefix
-}
-
-union Result {
-  1: PopulateJobResult populateJobResult
-  3: ScheduleStatusResult scheduleStatusResult
-  4: GetJobsResult getJobsResult
-  5: GetQuotaResult getQuotaResult
-  6: ListBackupsResult listBackupsResult
-  7: StartMaintenanceResult startMaintenanceResult
-  8: DrainHostsResult drainHostsResult
-  9: QueryRecoveryResult queryRecoveryResult
-  10: MaintenanceStatusResult maintenanceStatusResult
-  11: EndMaintenanceResult endMaintenanceResult
-  15: APIVersion getVersionResult
-  16: AcquireLockResult acquireLockResult
-  17: RoleSummaryResult roleSummaryResult
-  18: JobSummaryResult jobSummaryResult
-  19: GetLocksResult getLocksResult
-  20: ConfigSummaryResult configSummaryResult
-  21: GetPendingReasonResult getPendingReasonResult
-  22: StartJobUpdateResult startJobUpdateResult
-  23: GetJobUpdateSummariesResult getJobUpdateSummariesResult
-  24: GetJobUpdateDetailsResult getJobUpdateDetailsResult
-  25: PulseJobUpdateResult pulseJobUpdateResult
-}
-
-struct ResponseDetail {
-  1: string message
-}
-
-struct Response {
-  1: ResponseCode responseCode
-  // TODO(wfarner): Remove the message field in 0.7.0. (AURORA-466)
-  2: optional string messageDEPRECATED
-  // TODO(wfarner): Remove version field in 0.7.0. (AURORA-467)
-  4: APIVersion DEPRECATEDversion
-  5: ServerInfo serverInfo
-  /** Payload from the invoked RPC. */
-  3: optional Result result
-  /**
-   * Messages from the server relevant to the request, such as warnings or use of deprecated
-   * features.
-   */
-  6: list<ResponseDetail> details
-}
-
-// A service that provides all the read only calls to the Aurora scheduler.
-service ReadOnlyScheduler {
-  /** Returns a summary of the jobs grouped by role. */
-  Response getRoleSummary()
-
-  /** Returns a summary of jobs, optionally only those owned by a specific role. */
-  Response getJobSummary(1: string role)
-
-  /** Fetches the status of tasks. */
-  Response getTasksStatus(1: TaskQuery query)
-
-  /**
-   * Same as getTaskStatus but without the TaskConfig.ExecutorConfig data set.
-   * This is an interim solution until we have a better way to query TaskConfigs (AURORA-541).
-   */
-  Response getTasksWithoutConfigs(1: TaskQuery query)
-
-  /** Returns user-friendly reasons (if available) for tasks retained in PENDING state. */
-  Response getPendingReason(1: TaskQuery query)
-
-  /** Fetches the configuration summary of active tasks for the specified job. */
-  Response getConfigSummary(1: JobKey job)
-
-  /**
-   * Fetches the status of jobs.
-   * ownerRole is optional, in which case all jobs are returned.
-   */
-  Response getJobs(1: string ownerRole)
-
-  /** Fetches the quota allocated for a user. */
-  Response getQuota(1: string ownerRole)
-
-  // TODO(Suman Karumuri): Delete this API once it is no longer used.
-  /**
-   * Returns the current version of the API implementation
-   * NOTE: This method is deprecated.
-   */
-  Response getVersion()
-
-  /**
-   * Populates fields in a job configuration as though it were about to be run.
-   * This can be used to diff a configuration running tasks.
-   */
-  Response populateJobConfig(1: JobConfiguration description)
-
-  /** Returns all stored context specific resource/operation locks. */
-  Response getLocks()
-
-  /** Gets job update summaries. Not implemented yet. */
-  Response getJobUpdateSummaries(1: JobUpdateQuery jobUpdateQuery)
-
-  /** Gets job update details. Not implemented yet. */
-  Response getJobUpdateDetails(1: string updateId)
-}
-
-// Due to assumptions in the client all authenticated RPCs must have a SessionKey as their
-// last argument. Note that the order in this file is what matters, and message numbers should still
-// never be reused.
-service AuroraSchedulerManager extends ReadOnlyScheduler {
-  /**
-   * Creates a new job.  The request will be denied if a job with the provided name already exists
-   * in the cluster.
-   */
-  Response createJob(1: JobConfiguration description, 3: Lock lock, 2: SessionKey session)
-
-  /**
-   * Enters a job into the cron schedule, without actually starting the job.
-   * If the job is already present in the schedule, this will update the schedule entry with the new
-   * configuration.
-   */
-  Response scheduleCronJob(1: JobConfiguration description, 3: Lock lock, 2: SessionKey session)
-
-  /**
-   * Removes a job from the cron schedule. The request will be denied if the job was not previously
-   * scheduled with scheduleCronJob.
-   */
-  Response descheduleCronJob(4: JobKey job, 3: Lock lock, 2: SessionKey session)
-
-  /**
-   * Starts a cron job immediately.  The request will be denied if the specified job does not
-   * exist for the role account, or the job is not a cron job.
-   */
-  Response startCronJob(4: JobKey job, 3: SessionKey session)
-
-  /** Restarts a batch of shards. */
-  Response restartShards(5: JobKey job, 3: set<i32> shardIds, 6: Lock lock 4: SessionKey session)
-
-  /** Initiates a kill on tasks. */
-  Response killTasks(1: TaskQuery query, 3: Lock lock, 2: SessionKey session)
-
-  /**
-   * Adds new instances specified by the AddInstancesConfig. A job represented by the JobKey must be
-   * protected by Lock.
-   */
-  Response addInstances(
-      1: AddInstancesConfig config,
-      2: Lock lock,
-      3: SessionKey session)
-
-  /**
-   * Creates and saves a new Lock instance guarding against multiple mutating operations within the
-   * context defined by LockKey.
-   */
-  Response acquireLock(1: LockKey lockKey, 2: SessionKey session)
-
-  /** Releases the lock acquired earlier in acquireLock call. */
-  Response releaseLock(1: Lock lock, 2: LockValidation validation, 3: SessionKey session)
-
-  /**
-   * Replaces the template (configuration) for the existing cron job.
-   * The cron job template (configuration) must exist for the call to succeed.
-   */
-  Response replaceCronTemplate(1: JobConfiguration config, 2: Lock lock, 3: SessionKey session)
-
-  /** Starts update of the existing service job. Not implemented yet. */
-  Response startJobUpdate(1: JobUpdateRequest request, 2: SessionKey session)
-
-  /**
-   * Pauses the update progress for the specified job. Can be resumed by resumeUpdate call.
-   * Not implemented yet.
-   */
-  Response pauseJobUpdate(1: JobKey jobKey, 2: SessionKey session)
-
-  /** Resumes progress of a previously paused job update. Not implemented yet. */
-  Response resumeJobUpdate(1: JobKey jobKey, 2: SessionKey session)
-
-  /** Permanently aborts the job update. Does not remove the update history. Not implemented yet. */
-  Response abortJobUpdate(1: JobKey jobKey, 2: SessionKey session)
-
-  /**
-   * Allows progress of the job update in case blockIfNoPulsesAfterMs is specified in
-   * JobUpdateSettings. Unblocks progress if the update was previously blocked.
-   * Responds with ResponseCode.INVALID_REQUEST in case an unknown updateId is specified.
-   */
-  Response pulseJobUpdate(1: string updateId, 2: SessionKey session)
-}
-
-struct InstanceConfigRewrite {
-  /** Key for the task to rewrite. */
-  1: InstanceKey instanceKey
-  /** The original configuration. */
-  2: TaskConfig oldTask
-  /** The rewritten configuration. */
-  3: TaskConfig rewrittenTask
-}
-
-struct JobConfigRewrite {
-  /** The original job configuration. */
-  1: JobConfiguration oldJob
-  /** The rewritten job configuration. */
-  2: JobConfiguration rewrittenJob
-}
-
-union ConfigRewrite {
-  1: JobConfigRewrite jobRewrite
-  2: InstanceConfigRewrite instanceRewrite
-}
-
-struct RewriteConfigsRequest {
-  1: list<ConfigRewrite> rewriteCommands
-}
-
-// It would be great to compose these services rather than extend, but that won't be possible until
-// https://issues.apache.org/jira/browse/THRIFT-66 is resolved.
-service AuroraAdmin extends AuroraSchedulerManager {
-  /** Assign quota to a user.  This will overwrite any pre-existing quota for the user. */
-  Response setQuota(1: string ownerRole, 2: ResourceAggregate quota, 3: SessionKey session)
-
-  /**
-   * Forces a task into a specific state.  This does not guarantee the task will enter the given
-   * state, as the task must still transition within the bounds of the state machine.  However,
-   * it attempts to enter that state via the state machine.
-   */
-  Response forceTaskState(
-      1: string taskId,
-      2: ScheduleStatus status,
-      3: SessionKey session)
-
-  /** Immediately writes a storage snapshot to disk. */
-  Response performBackup(1: SessionKey session)
-
-  /** Lists backups that are available for recovery. */
-  Response listBackups(1: SessionKey session)
-
-  /** Loads a backup to an in-memory storage.  This must precede all other recovery operations. */
-  Response stageRecovery(1: string backupId, 2: SessionKey session)
-
-  /** Queries for tasks in a staged recovery. */
-  Response queryRecovery(1: TaskQuery query, 2: SessionKey session)
-
-  /** Deletes tasks from a staged recovery. */
-  Response deleteRecoveryTasks(1: TaskQuery query, 2: SessionKey session)
-
-  /** Commits a staged recovery, completely replacing the previous storage state. */
-  Response commitRecovery(1: SessionKey session)
-
-  /** Unloads (aborts) a staged recovery. */
-  Response unloadRecovery(1: SessionKey session)
-
-  /** Put the given hosts into maintenance mode. */
-  Response startMaintenance(1: Hosts hosts, 2: SessionKey session)
-
-  /** Ask scheduler to begin moving tasks scheduled on given hosts. */
-  Response drainHosts(1: Hosts hosts, 2: SessionKey session)
-
-  /** Retrieve the current maintenance states for a group of hosts. */
-  Response maintenanceStatus(1: Hosts hosts, 2: SessionKey session)
-
-  /** Set the given hosts back into serving mode. */
-  Response endMaintenance(1: Hosts hosts, 2: SessionKey session)
-
-  /** Start a storage snapshot and block until it completes. */
-  Response snapshot(1: SessionKey session)
-
-  /**
-   * Forcibly rewrites the stored definition of user configurations.  This is intended to be used
-   * in a controlled setting, primarily to migrate pieces of configurations that are opaque to the
-   * scheduler (e.g. executorConfig).
-   * The scheduler may do some validation of the rewritten configurations, but it is important
-   * that the caller take care to provide valid input and alter only necessary fields.
-   */
-  Response rewriteConfigs(1: RewriteConfigsRequest request, 2: SessionKey session)
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/91b8d193/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
----------------------------------------------------------------------
diff --git a/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift b/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
deleted file mode 100644
index a2c230f..0000000
--- a/src/main/thrift/org/apache/aurora/gen/internal_rpc.thrift
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace java org.apache.aurora.gen.comm
-namespace py gen.apache.aurora.comm
-
-include "api.thrift"
-
-// Thrift interface to define the communication between the scheduler and executor.
-
-// Message sent from the scheduler to the executor, indicating that some
-// task history associated with the host may have been purged, and the
-// executor should only retain tasks associated with the provided tasks IDs.
-struct AdjustRetainedTasks {
-  2: map<string, api.ScheduleStatus> retainedTasks  // All tasks that the executor should
-                                                    // retain, and their statuses.
-}