aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject git commit: Store new task configuration in JobUpdateConfiguration as InstanceTaskConfig
Date Thu, 18 Sep 2014 20:39:09 GMT
Repository: incubator-aurora
Updated Branches:
  refs/heads/master 1c4a1a880 -> 860dc4e98


Store new task configuration in JobUpdateConfiguration as InstanceTaskConfig

Bugs closed: AURORA-717

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


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

Branch: refs/heads/master
Commit: 860dc4e98840ebf4f55d6ef931bdf4667c9b5c4f
Parents: 1c4a1a8
Author: Maxim Khutornenko <maxim@apache.org>
Authored: Thu Sep 18 13:38:37 2014 -0700
Committer: Maxim Khutornenko <maxim@apache.org>
Committed: Thu Sep 18 13:38:37 2014 -0700

----------------------------------------------------------------------
 .../scheduler/storage/ForwardingStore.java      |   6 +-
 .../scheduler/storage/JobUpdateStore.java       |  10 +-
 .../scheduler/storage/db/DBJobUpdateStore.java  |  27 +++--
 .../storage/db/JobUpdateDetailsMapper.java      |  21 +++-
 .../thrift/SchedulerThriftInterface.java        |  15 ++-
 .../updater/InstanceActionHandler.java          |  24 ++--
 .../updater/JobUpdateControllerImpl.java        |   6 +-
 .../aurora/scheduler/updater/UpdateFactory.java |  30 +++--
 .../aurora/scheduler/http/ui/js/controllers.js  |   2 +-
 .../aurora/scheduler/http/ui/js/services.js     |  14 ++-
 .../scheduler/http/ui/updateSettings.html       |  16 +--
 .../storage/db/JobUpdateDetailsMapper.xml       | 112 +++++++++++--------
 .../aurora/scheduler/storage/db/schema.sql      |  10 +-
 .../thrift/org/apache/aurora/gen/api.thrift     |  15 +--
 .../storage/db/DBJobUpdateStoreTest.java        |  44 +++++---
 .../scheduler/storage/log/LogStorageTest.java   |  11 +-
 .../thrift/SchedulerThriftInterfaceTest.java    |  28 +++--
 .../aurora/scheduler/updater/AddTaskTest.java   |  10 +-
 .../aurora/scheduler/updater/JobUpdaterIT.java  |  31 ++---
 .../updater/UpdateFactoryImplTest.java          |  41 +++----
 .../org/apache/aurora/gen/api.thrift.md5        |   2 +-
 21 files changed, 270 insertions(+), 205 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/storage/ForwardingStore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/ForwardingStore.java b/src/main/java/org/apache/aurora/scheduler/storage/ForwardingStore.java
index 5ac42b6..1874a3e 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/ForwardingStore.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/ForwardingStore.java
@@ -26,8 +26,8 @@ import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
 import org.apache.aurora.scheduler.storage.entities.IJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
 import org.apache.aurora.scheduler.storage.entities.ILock;
@@ -158,8 +158,8 @@ public class ForwardingStore implements
   }
 
   @Override
-  public Optional<IJobUpdateConfiguration> fetchJobUpdateConfiguration(String updateId) {
-    return jobUpdateStore.fetchJobUpdateConfiguration(updateId);
+  public Optional<IJobUpdateInstructions> fetchJobUpdateInstructions(String updateId) {
+    return jobUpdateStore.fetchJobUpdateInstructions(updateId);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/storage/JobUpdateStore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/JobUpdateStore.java b/src/main/java/org/apache/aurora/scheduler/storage/JobUpdateStore.java
index dfaadc8..920ff3e 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/JobUpdateStore.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/JobUpdateStore.java
@@ -21,9 +21,9 @@ import com.google.common.base.Optional;
 import org.apache.aurora.gen.storage.StoredJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
 
@@ -57,12 +57,12 @@ public interface JobUpdateStore {
   Optional<IJobUpdate> fetchJobUpdate(String updateId);
 
   /**
-   * Fetches a read-only view of a job update configuration.
+   * Fetches a read-only view of the instructions for a job update.
    *
-   * @param updateId Update ID to fetch configuration for.
-   * @return A read-only view of job update configuration.
+   * @param updateId Update ID to fetch instructions for.
+   * @return A read-only view of job update instructions.
    */
-  Optional<IJobUpdateConfiguration> fetchJobUpdateConfiguration(String updateId);
+  Optional<IJobUpdateInstructions> fetchJobUpdateInstructions(String updateId);
 
   /**
    * Fetches a read-only view of all job update details available in the store.

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStore.java b/src/main/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStore.java
index 0737f92..cb2e768 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStore.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStore.java
@@ -23,15 +23,15 @@ import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
 
 import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateConfiguration;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.storage.StoredJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.JobUpdateStore;
 import org.apache.aurora.scheduler.storage.entities.IInstanceTaskConfig;
 import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
 import org.apache.aurora.scheduler.storage.entities.IRange;
@@ -74,21 +74,24 @@ public class DBJobUpdateStore implements JobUpdateStore.Mutable {
 
     // Insert optional instance update overrides.
     Set<IRange> instanceOverrides =
-        update.getConfiguration().getSettings().getUpdateOnlyTheseInstances();
+        update.getInstructions().getSettings().getUpdateOnlyTheseInstances();
 
     if (!instanceOverrides.isEmpty()) {
       detailsMapper.insertInstanceOverrides(updateId, IRange.toBuildersSet(instanceOverrides));
     }
 
-    // Insert new task config.
+    // Insert desired state task config and instance mappings.
+    IInstanceTaskConfig desired = update.getInstructions().getDesiredState();
     detailsMapper.insertTaskConfig(
         updateId,
-        update.getConfiguration().getNewTaskConfig().newBuilder(),
+        desired.getTask().newBuilder(),
         true,
         new InsertResult());
 
-    // Insert old task configs and instance mappings.
-    for (IInstanceTaskConfig config : update.getConfiguration().getOldTaskConfigs()) {
+    detailsMapper.insertDesiredInstances(updateId, IRange.toBuildersSet(desired.getInstances()));
+
+    // Insert initial state task configs and instance mappings.
+    for (IInstanceTaskConfig config : update.getInstructions().getInitialState()) {
       InsertResult result = new InsertResult();
       detailsMapper.insertTaskConfig(updateId, config.getTask().newBuilder(), false, result);
 
@@ -141,12 +144,12 @@ public class DBJobUpdateStore implements JobUpdateStore.Mutable {
   }
 
   @Override
-  public Optional<IJobUpdateConfiguration> fetchJobUpdateConfiguration(String updateId) {
-    return Optional.fromNullable(detailsMapper.selectConfiguration(updateId))
-        .transform(new Function<JobUpdateConfiguration, IJobUpdateConfiguration>() {
+  public Optional<IJobUpdateInstructions> fetchJobUpdateInstructions(String updateId) {
+    return Optional.fromNullable(detailsMapper.selectInstructions(updateId))
+        .transform(new Function<JobUpdateInstructions, IJobUpdateInstructions>() {
           @Override
-          public IJobUpdateConfiguration apply(JobUpdateConfiguration input) {
-            return IJobUpdateConfiguration.build(input);
+          public IJobUpdateInstructions apply(JobUpdateInstructions input) {
+            return IJobUpdateInstructions.build(input);
           }
         });
   }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.java
index 04a9246..26cc85d 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.java
@@ -19,7 +19,7 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateConfiguration;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateQuery;
 import org.apache.aurora.gen.JobUpdateSummary;
 import org.apache.aurora.gen.Range;
@@ -80,13 +80,24 @@ interface JobUpdateDetailsMapper {
    * {@link org.apache.aurora.gen.JobUpdateSettings#updateOnlyTheseInstances}.
    *
    * @param updateId Update ID to store overrides for.
-   * @param ranges Instance ID ranges to associate with a task configuration.
+   * @param ranges Instance ID ranges to associate with an update.
    */
   void insertInstanceOverrides(
       @Param("updateId") String updateId,
       @Param("ranges") Set<Range> ranges);
 
   /**
+   * Maps update with a set of instance IDs in
+   * {@link org.apache.aurora.gen.JobUpdateInstructions#desiredState}.
+   *
+   * @param updateId Update ID to store desired instances for.
+   * @param ranges Desired instance ID ranges to associate with an update.
+   */
+  void insertDesiredInstances(
+      @Param("updateId") String updateId,
+      @Param("ranges") Set<Range> ranges);
+
+  /**
    * Deletes all updates and events from the database.
    */
   void truncate();
@@ -119,13 +130,13 @@ interface JobUpdateDetailsMapper {
   JobUpdate selectUpdate(String updateId);
 
   /**
-   * Gets job update configuration for the provided {@code updateId}.
+   * Gets job update instructions for the provided {@code updateId}.
    *
    * @param updateId Update ID to select by.
-   * @return job update configuration for the provided update ID, if it exists.
+   * @return job update instructions for the provided update ID, if it exists.
    */
   @Nullable
-  JobUpdateConfiguration selectConfiguration(String updateId);
+  JobUpdateInstructions selectInstructions(String updateId);
 
   /**
    * Gets all stored job update details.

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java b/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
index d4b8141..83ac034 100644
--- a/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
+++ b/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
@@ -74,7 +74,7 @@ import org.apache.aurora.gen.JobKey;
 import org.apache.aurora.gen.JobSummary;
 import org.apache.aurora.gen.JobSummaryResult;
 import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateConfiguration;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateQuery;
 import org.apache.aurora.gen.JobUpdateRequest;
 import org.apache.aurora.gen.JobUpdateSummary;
@@ -1328,7 +1328,7 @@ class SchedulerThriftInterface implements AuroraAdmin.Iface {
         }
       };
 
-  private static Set<InstanceTaskConfig> buildOldTaskConfigs(
+  private static Set<InstanceTaskConfig> buildInitialState(
       IJobKey jobKey,
       Storage.StoreProvider storeProvider) {
 
@@ -1405,11 +1405,14 @@ class SchedulerThriftInterface implements AuroraAdmin.Iface {
                 .setJobKey(request.getJobKey().newBuilder())
                 .setUpdateId(updateId)
                 .setUser(context.getIdentity()))
-            .setConfiguration(new JobUpdateConfiguration()
+            .setInstructions(new JobUpdateInstructions()
                 .setSettings(request.getSettings().newBuilder())
-                .setInstanceCount(request.getInstanceCount())
-                .setNewTaskConfig(request.getTaskConfig().newBuilder())
-                .setOldTaskConfigs(buildOldTaskConfigs(request.getJobKey(), storeProvider))));
+                .setInitialState(buildInitialState(request.getJobKey(), storeProvider))
+                .setDesiredState(new InstanceTaskConfig()
+                    .setTask(request.getTaskConfig().newBuilder())
+                    .setInstances(ImmutableSet.of(new org.apache.aurora.gen.Range()
+                        .setFirst(0)
+                        .setLast(request.getInstanceCount() - 1))))));
 
         try {
           jobUpdateController.start(update, context.getIdentity());

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/updater/InstanceActionHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/updater/InstanceActionHandler.java b/src/main/java/org/apache/aurora/scheduler/updater/InstanceActionHandler.java
index 2538291..b271697 100644
--- a/src/main/java/org/apache/aurora/scheduler/updater/InstanceActionHandler.java
+++ b/src/main/java/org/apache/aurora/scheduler/updater/InstanceActionHandler.java
@@ -30,7 +30,7 @@ import org.apache.aurora.scheduler.state.StateManager;
 import org.apache.aurora.scheduler.storage.TaskStore;
 import org.apache.aurora.scheduler.storage.entities.IInstanceKey;
 import org.apache.aurora.scheduler.storage.entities.IInstanceTaskConfig;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IRange;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 
@@ -40,7 +40,7 @@ interface InstanceActionHandler {
 
   Amount<Long, Time> getReevaluationDelay(
       IInstanceKey instance,
-      IJobUpdateConfiguration updateConfig,
+      IJobUpdateInstructions instructions,
       TaskStore taskStore,
       StateManager stateManager,
       JobUpdateStatus status);
@@ -49,14 +49,14 @@ interface InstanceActionHandler {
 
   class AddTask implements InstanceActionHandler {
     private static ITaskConfig getTargetConfig(
-        IJobUpdateConfiguration configuration,
+        IJobUpdateInstructions instructions,
         boolean rollingForward,
         int instanceId) {
 
       if (rollingForward) {
-        return configuration.getNewTaskConfig();
+        return instructions.getDesiredState().getTask();
       } else {
-        for (IInstanceTaskConfig config : configuration.getOldTaskConfigs()) {
+        for (IInstanceTaskConfig config : instructions.getInitialState()) {
           for (IRange range : config.getInstances()) {
             if (Range.closed(range.getFirst(), range.getLast()).contains(instanceId)) {
               return config.getTask();
@@ -71,7 +71,7 @@ interface InstanceActionHandler {
     @Override
     public Amount<Long, Time> getReevaluationDelay(
         IInstanceKey instance,
-        IJobUpdateConfiguration updateConfig,
+        IJobUpdateInstructions instructions,
         TaskStore taskStore,
         StateManager stateManager,
         JobUpdateStatus status) {
@@ -80,12 +80,12 @@ interface InstanceActionHandler {
       // quota checking to take updates into consideration (AURORA-686).
       LOG.info("Adding instance " + instance + " while " + status);
       ITaskConfig replacement = getTargetConfig(
-          updateConfig,
+          instructions,
           status == ROLLING_FORWARD,
           instance.getInstanceId());
       stateManager.insertPendingTasks(replacement, ImmutableSet.of(instance.getInstanceId()));
       return  Amount.of(
-          (long) updateConfig.getSettings().getMaxWaitToInstanceRunningMs(),
+          (long) instructions.getSettings().getMaxWaitToInstanceRunningMs(),
           Time.MILLISECONDS);
     }
   }
@@ -94,7 +94,7 @@ interface InstanceActionHandler {
     @Override
     public Amount<Long, Time> getReevaluationDelay(
         IInstanceKey instance,
-        IJobUpdateConfiguration updateConfig,
+        IJobUpdateInstructions instructions,
         TaskStore taskStore,
         StateManager stateManager,
         JobUpdateStatus status) {
@@ -108,7 +108,7 @@ interface InstanceActionHandler {
           ScheduleStatus.KILLING,
           Optional.of("Killed for job update."));
       return Amount.of(
-          (long) updateConfig.getSettings().getMaxWaitToInstanceRunningMs(),
+          (long) instructions.getSettings().getMaxWaitToInstanceRunningMs(),
           Time.MILLISECONDS);
     }
   }
@@ -117,13 +117,13 @@ interface InstanceActionHandler {
     @Override
     public Amount<Long, Time> getReevaluationDelay(
         IInstanceKey instance,
-        IJobUpdateConfiguration updateConfig,
+        IJobUpdateInstructions instructions,
         TaskStore taskStore,
         StateManager stateManager,
         JobUpdateStatus status) {
 
       return Amount.of(
-          (long) updateConfig.getSettings().getMinWaitInInstanceRunningMs(),
+          (long) instructions.getSettings().getMinWaitInInstanceRunningMs(),
           Time.MILLISECONDS);
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/updater/JobUpdateControllerImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/updater/JobUpdateControllerImpl.java b/src/main/java/org/apache/aurora/scheduler/updater/JobUpdateControllerImpl.java
index 33bf7c7..5375ed2 100644
--- a/src/main/java/org/apache/aurora/scheduler/updater/JobUpdateControllerImpl.java
+++ b/src/main/java/org/apache/aurora/scheduler/updater/JobUpdateControllerImpl.java
@@ -124,7 +124,7 @@ class JobUpdateControllerImpl implements JobUpdateController {
     requireNonNull(updatingUser);
 
     // Validate the update configuration by making sure we can create an updater for it.
-    updateFactory.newUpdate(update.getConfiguration(), true);
+    updateFactory.newUpdate(update.getInstructions(), true);
 
     storage.write(new MutateWork.NoResult<UpdateStateException>() {
       @Override
@@ -380,7 +380,7 @@ class JobUpdateControllerImpl implements JobUpdateController {
       IJobUpdate jobUpdate = updateStore.fetchJobUpdate(updateId).get();
       UpdateFactory.Update update;
       try {
-        update = updateFactory.newUpdate(jobUpdate.getConfiguration(), action == ROLL_FORWARD);
+        update = updateFactory.newUpdate(jobUpdate.getInstructions(), action == ROLL_FORWARD);
       } catch (UpdateConfigurationException | RuntimeException e) {
         changeJobUpdateStatus(updateStore, taskStore, updateId, job, ERROR, true);
         return;
@@ -458,7 +458,7 @@ class JobUpdateControllerImpl implements JobUpdateController {
           if (handler.isPresent()) {
             Amount<Long, Time> reevaluateDelay = handler.get().getReevaluationDelay(
                 instance,
-                updateStore.fetchJobUpdateConfiguration(summary.getUpdateId()).get(),
+                updateStore.fetchJobUpdateInstructions(summary.getUpdateId()).get(),
                 taskStore,
                 stateManager,
                 updaterStatus);

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/java/org/apache/aurora/scheduler/updater/UpdateFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/updater/UpdateFactory.java b/src/main/java/org/apache/aurora/scheduler/updater/UpdateFactory.java
index 029c105..842256a 100644
--- a/src/main/java/org/apache/aurora/scheduler/updater/UpdateFactory.java
+++ b/src/main/java/org/apache/aurora/scheduler/updater/UpdateFactory.java
@@ -31,7 +31,7 @@ import com.twitter.common.util.Clock;
 
 import org.apache.aurora.gen.JobUpdateStatus;
 import org.apache.aurora.scheduler.storage.entities.IInstanceTaskConfig;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSettings;
 import org.apache.aurora.scheduler.storage.entities.IRange;
 import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
@@ -61,7 +61,7 @@ interface UpdateFactory {
    * @throws UpdateConfigurationException If the provided configuration cannot be used.
    */
   Update newUpdate(
-      IJobUpdateConfiguration configuration,
+      IJobUpdateInstructions configuration,
       boolean rollingForward) throws UpdateConfigurationException;
 
   class UpdateFactoryImpl implements UpdateFactory {
@@ -74,11 +74,11 @@ interface UpdateFactory {
 
     @Override
     public Update newUpdate(
-        IJobUpdateConfiguration configuration,
+        IJobUpdateInstructions instructions,
         boolean rollingForward) throws UpdateConfigurationException {
 
-      requireNonNull(configuration);
-      IJobUpdateSettings settings = configuration.getSettings();
+      requireNonNull(instructions);
+      IJobUpdateSettings settings = instructions.getSettings();
       checkArgument(
           settings.getMaxWaitToInstanceRunningMs() > 0,
           "Max wait to running must be positive.");
@@ -89,25 +89,23 @@ interface UpdateFactory {
           settings.getUpdateGroupSize() > 0,
           "Update group size must be positive.");
       checkArgument(
-          configuration.getInstanceCount() > 0,
+          !instructions.getDesiredState().getInstances().isEmpty(),
           "Instance count must be positive.");
 
       Set<Integer> instances;
-      Range<Integer> updateConfigurationInstances =
-          Range.closedOpen(0, configuration.getInstanceCount());
-      if (settings.getUpdateOnlyTheseInstances().isEmpty()) {
-        Set<Integer> newInstanceIds =
-            ImmutableRangeSet.of(updateConfigurationInstances).asSet(DiscreteDomain.integers());
+      Set<Integer> desiredInstances =
+          expandInstanceIds(ImmutableSet.of(instructions.getDesiredState()));
 
+      if (settings.getUpdateOnlyTheseInstances().isEmpty()) {
         // In a full job update, the working set is the union of instance IDs before and after.
         instances =  ImmutableSet.copyOf(
-            Sets.union(expandInstanceIds(configuration.getOldTaskConfigs()), newInstanceIds));
+            Sets.union(expandInstanceIds(instructions.getInitialState()), desiredInstances));
       } else {
         instances = rangesToInstanceIds(settings.getUpdateOnlyTheseInstances());
 
         // TODO(wfarner): Move this check out to SchedulerThriftInterface, and remove the
         // UpdateConfigurationException from this method's signature.
-        if (!updateConfigurationInstances.containsAll(instances)) {
+        if (!desiredInstances.containsAll(instances)) {
           throw new UpdateConfigurationException(
               "When updating specific instances, "
                   + "all specified instances must be in the update configuration.");
@@ -119,11 +117,11 @@ interface UpdateFactory {
       for (int instanceId : instances) {
         Optional<ITaskConfig> desiredState;
         if (rollingForward) {
-          desiredState = updateConfigurationInstances.contains(instanceId)
-              ? Optional.of(configuration.getNewTaskConfig())
+          desiredState = desiredInstances.contains(instanceId)
+              ? Optional.of(instructions.getDesiredState().getTask())
               : Optional.<ITaskConfig>absent();
         } else {
-          desiredState = getConfig(instanceId, configuration.getOldTaskConfigs());
+          desiredState = getConfig(instanceId, instructions.getInitialState());
         }
 
         evaluators.put(

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/resources/org/apache/aurora/scheduler/http/ui/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/http/ui/js/controllers.js b/src/main/resources/org/apache/aurora/scheduler/http/ui/js/controllers.js
index 0884cc8..a454b26 100644
--- a/src/main/resources/org/apache/aurora/scheduler/http/ui/js/controllers.js
+++ b/src/main/resources/org/apache/aurora/scheduler/http/ui/js/controllers.js
@@ -247,7 +247,7 @@
 
         $scope.stats = updateUtil.getUpdateStats($scope.update);
         $scope.configJson = JSON
-          .stringify($scope.update.update.configuration.newTaskConfig, undefined, 2);
+          .stringify($scope.update.update.instructions.desiredState.task, undefined, 2);
 
         // pagination for instance events
         var instanceEvents = $scope.instanceEvents = $scope.update.instanceEvents;

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/resources/org/apache/aurora/scheduler/http/ui/js/services.js
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/http/ui/js/services.js b/src/main/resources/org/apache/aurora/scheduler/http/ui/js/services.js
index f79acd2..7d9c646 100644
--- a/src/main/resources/org/apache/aurora/scheduler/http/ui/js/services.js
+++ b/src/main/resources/org/apache/aurora/scheduler/http/ui/js/services.js
@@ -282,11 +282,11 @@
           // new instance count and old instance count
           var totalInstances = Math.max(
               stats.oldInstanceCount,
-              details.update.configuration.instanceCount
+              updateUtil.instanceCountFromRanges(details.update.instructions.desiredState.instances)
             );
 
           var instances = [];
-          var instanceSubset = details.update.configuration.settings.updateOnlyTheseInstances;
+          var instanceSubset = details.update.instructions.settings.updateOnlyTheseInstances;
 
           function inRanges(ranges, x) {
             if (ranges && x) {
@@ -331,19 +331,21 @@
           }
 
           // find number of instances to be updated
-          var newInstanceCount = details.update.configuration.instanceCount;
+          var newInstanceCount = updateUtil.instanceCountFromRanges(
+            details.update.instructions.desiredState.instances
+          );
           var updateSubset = false;
 
           // find total number of existing instances
           var oldInstanceCount = updateUtil.instanceCountFromConfigs(
-            details.update.configuration.oldTaskConfigs);
+            details.update.instructions.initialState);
 
           // max of those two numbers is the number of instances to be updated
           var totalInstancesToBeUpdated = Math.max(oldInstanceCount, newInstanceCount);
 
-          if (details.update.configuration.settings.updateOnlyTheseInstances) {
+          if (details.update.instructions.settings.updateOnlyTheseInstances) {
             newInstanceCount = updateUtil.instanceCountFromRanges(
-              details.update.configuration.settings.updateOnlyTheseInstances
+              details.update.instructions.settings.updateOnlyTheseInstances
             );
             updateSubset = true;
             totalInstancesToBeUpdated = newInstanceCount;

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/resources/org/apache/aurora/scheduler/http/ui/updateSettings.html
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/http/ui/updateSettings.html b/src/main/resources/org/apache/aurora/scheduler/http/ui/updateSettings.html
index 613b532..5e48402 100644
--- a/src/main/resources/org/apache/aurora/scheduler/http/ui/updateSettings.html
+++ b/src/main/resources/org/apache/aurora/scheduler/http/ui/updateSettings.html
@@ -23,7 +23,7 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.updateGroupSize}}</strong>
+      <strong>{{update.update.instructions.settings.updateGroupSize}}</strong>
     </td>
   </tr>
   <tr>
@@ -33,7 +33,7 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.maxPerInstanceFailures}}</strong>
+      <strong>{{update.update.instructions.settings.maxPerInstanceFailures}}</strong>
     </td>
   </tr>
   <tr>
@@ -43,7 +43,7 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.maxFailedInstances}}</strong>
+      <strong>{{update.update.instructions.settings.maxFailedInstances}}</strong>
     </td>
   </tr>
   <tr>
@@ -53,7 +53,7 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.maxWaitToInstanceRunningMs}}</strong>
+      <strong>{{update.update.instructions.settings.maxWaitToInstanceRunningMs}}</strong>
     </td>
   </tr>
   <tr>
@@ -63,7 +63,7 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.minWaitInInstanceRunningMs}}</strong>
+      <strong>{{update.update.instructions.settings.minWaitInInstanceRunningMs}}</strong>
     </td>
   </tr>
   <tr>
@@ -73,17 +73,17 @@
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.rollbackOnFailure}}</strong>
+      <strong>{{update.update.instructions.settings.rollbackOnFailure}}</strong>
     </td>
   </tr>
-  <tr ng-if="update.update.configuration.settings.updateOnlyTheseInstances">
+  <tr ng-if="update.update.instructions.settings.updateOnlyTheseInstances">
     <td>
       <span class="setting-label" tooltip="A subset of instance IDs to act on. All instances will be affected if this is not set.">
         Instance IDs
       </span>
     </td>
     <td>
-      <strong>{{update.update.configuration.settings.updateOnlyTheseInstances | toNiceRanges}}</strong>
+      <strong>{{update.update.instructions.settings.updateOnlyTheseInstances | toNiceRanges}}</strong>
     </td>
   </tr>
 </table>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/resources/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.xml
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.xml b/src/main/resources/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.xml
index 0e7f6eb..ad877ed 100644
--- a/src/main/resources/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.xml
+++ b/src/main/resources/org/apache/aurora/scheduler/storage/db/JobUpdateDetailsMapper.xml
@@ -30,7 +30,6 @@
       job_key_id,
       update_id,
       user,
-      instance_count,
       update_group_size,
       max_per_instance_failures,
       max_failed_instances,
@@ -47,13 +46,12 @@
       ),
       #{summary.updateId},
       #{summary.user},
-      #{configuration.instanceCount},
-      #{configuration.settings.updateGroupSize},
-      #{configuration.settings.maxPerInstanceFailures},
-      #{configuration.settings.maxFailedInstances},
-      #{configuration.settings.maxWaitToInstanceRunningMs},
-      #{configuration.settings.minWaitInInstanceRunningMs},
-      #{configuration.settings.rollbackOnFailure}
+      #{instructions.settings.updateGroupSize},
+      #{instructions.settings.maxPerInstanceFailures},
+      #{instructions.settings.maxFailedInstances},
+      #{instructions.settings.maxWaitToInstanceRunningMs},
+      #{instructions.settings.minWaitInInstanceRunningMs},
+      #{instructions.settings.rollbackOnFailure}
     )
   </insert>
 
@@ -79,6 +77,14 @@
     )
   </insert>
 
+  <sql id="insertInstanceRanges">
+    <foreach item="element" collection="ranges" open="(" separator="),(" close=")">
+      <include refid="selectUpdateIdentity"/>,
+      #{element.first},
+      #{element.last}
+    </foreach>
+  </sql>
+
   <insert id="insertTaskConfigInstances">
     INSERT INTO job_update_configs_to_instances (
       config_id,
@@ -98,11 +104,16 @@
       first,
       last
     ) VALUES
-    <foreach item="element" collection="ranges" open="(" separator="),(" close=")">
-      <include refid="selectUpdateIdentity"/>,
-      #{element.first},
-      #{element.last}
-    </foreach>
+  <include refid="insertInstanceRanges" />
+  </insert>
+
+  <insert id="insertDesiredInstances">
+    INSERT INTO job_updates_to_desired_instances (
+      update_id,
+      first,
+      last
+    ) VALUES
+    <include refid="insertInstanceRanges" />
   </insert>
 
   <resultMap id="jobUpdateStateMap" type="org.apache.aurora.gen.JobUpdateState">
@@ -142,22 +153,20 @@
                 notNullColumn="id" />
   </resultMap>
 
-  <resultMap id="jobUpdateConfigurationMap" type="org.apache.aurora.gen.JobUpdateConfiguration">
+  <resultMap id="jobUpdateInstructionMap" type="org.apache.aurora.gen.JobUpdateInstructions">
     <id column="id" />
-    <result property="newTaskConfig"
-            column="new_task_config"
-            typeHandler="org.apache.aurora.scheduler.storage.db.typehandlers.TaskConfigTypeHandler" />
+    <association property="desiredState" resultMap="instanceConfigMap" columnPrefix="ditc_" />
     <association property="settings" resultMap="jobUpdateSettingsMap" columnPrefix="juse_"/>
-    <collection property="oldTaskConfigs"
+    <collection property="initialState"
                 resultMap="instanceConfigMap"
-                columnPrefix="itc_"
+                columnPrefix="iitc_"
                 notNullColumn="id" />
   </resultMap>
 
   <resultMap id="jobUpdateMap" type="org.apache.aurora.gen.JobUpdate">
     <id column="u_id" />
     <association property="summary" resultMap="jobUpdateSummaryMap" columnPrefix="jusm_"/>
-    <association property="configuration" resultMap="jobUpdateConfigurationMap" columnPrefix="juc_"/>
+    <association property="instructions" resultMap="jobUpdateInstructionMap" columnPrefix="jui_"/>
   </resultMap>
 
   <resultMap id="jobUpdateDetailsMap" type="org.apache.aurora.gen.storage.StoredJobUpdateDetails">
@@ -282,24 +291,27 @@
       j.role AS jusm_jk_role,
       j.environment AS jusm_jk_environment,
       j.name AS jusm_jk_name,
-      u.id AS juc_juse_id,
-      u.instance_count AS juc_instance_count,
-      u.update_group_size AS juc_juse_update_group_size,
-      u.max_per_instance_failures AS juc_juse_max_per_instance_failures,
-      u.max_failed_instances AS juc_juse_max_failed_instances,
-      u.max_wait_to_instance_running_ms AS juc_juse_max_wait_to_instance_running_ms,
-      u.min_wait_in_instance_running_ms AS juc_juse_min_wait_in_instance_running_ms,
-      u.rollback_on_failure AS juc_juse_rollback_on_failure,
-      cn.id AS juc_id,
-      cn.task_config AS juc_new_task_config,
-      co.id AS juc_itc_id,
-      co.task_config AS juc_itc_task,
-      ci.id AS juc_itc_r_id,
-      ci.first AS juc_itc_r_first,
-      ci.last AS juc_itc_r_last,
-      io.id AS juc_juse_r_id,
-      io.first AS juc_juse_r_first,
-      io.last AS juc_juse_r_last
+      u.id AS jui_juse_id,
+      u.update_group_size AS jui_juse_update_group_size,
+      u.max_per_instance_failures AS jui_juse_max_per_instance_failures,
+      u.max_failed_instances AS jui_juse_max_failed_instances,
+      u.max_wait_to_instance_running_ms AS jui_juse_max_wait_to_instance_running_ms,
+      u.min_wait_in_instance_running_ms AS jui_juse_min_wait_in_instance_running_ms,
+      u.rollback_on_failure AS jui_juse_rollback_on_failure,
+      cn.id AS jui_id,
+      cn.id AS jui_ditc_id,
+      cn.task_config AS jui_ditc_task,
+      di.id AS jui_ditc_r_id,
+      di.first AS jui_ditc_r_first,
+      di.last AS jui_ditc_r_last,
+      co.id AS jui_iitc_id,
+      co.task_config AS jui_iitc_task,
+      ci.id AS jui_iitc_r_id,
+      ci.first AS jui_iitc_r_first,
+      ci.last AS jui_iitc_r_last,
+      io.id AS jui_juse_r_id,
+      io.first AS jui_juse_r_first,
+      io.last AS jui_juse_r_last
   </sql>
 
   <sql id="job_update_to_configs_inner_joins">
@@ -308,6 +320,7 @@
     INNER JOIN job_update_configs AS cn ON cn.update_id = u.id AND cn.is_new = TRUE
     INNER JOIN job_update_configs AS co ON co.update_id = u.id AND co.is_new = FALSE
     INNER JOIN job_update_configs_to_instances AS ci ON ci.config_id = co.id
+    INNER JOIN job_updates_to_desired_instances AS di ON di.update_id = u.id
   </sql>
 
   <sql id="job_update_to_instance_overrides_outer_join">
@@ -333,13 +346,12 @@
     LEFT OUTER JOIN job_update_locks AS l on l.update_id = u.id
   </sql>
 
-  <!--Ideally, update configuration columns could be derived from job_update_columns above but that
-      hits against the limits of mybatis code reuse as specifying a common "juc_" column prefix
+  <!--Ideally, update instruction columns could be derived from job_update_columns above but that
+      hits against the limits of mybatis code reuse as specifying a common "jui_" column prefix
       in case of a standalone (no parent association) select appears to be impossible.-->
-  <select id="selectConfiguration" resultMap="jobUpdateConfigurationMap">
+  <select id="selectInstructions" resultMap="jobUpdateInstructionMap">
     SELECT
       u.id AS juse_id,
-      u.instance_count AS instance_count,
       u.update_group_size AS juse_update_group_size,
       u.max_per_instance_failures AS juse_max_per_instance_failures,
       u.max_failed_instances AS juse_max_failed_instances,
@@ -347,12 +359,16 @@
       u.min_wait_in_instance_running_ms AS juse_min_wait_in_instance_running_ms,
       u.rollback_on_failure AS juse_rollback_on_failure,
       cn.id AS id,
-      cn.task_config AS new_task_config,
-      co.id AS itc_id,
-      co.task_config AS itc_task,
-      ci.id AS itc_r_id,
-      ci.first AS itc_r_first,
-      ci.last AS itc_r_last,
+      cn.id AS ditc_id,
+      cn.task_config AS ditc_task,
+      di.id AS ditc_r_id,
+      di.first AS ditc_r_first,
+      di.last AS ditc_r_last,
+      co.id AS iitc_id,
+      co.task_config AS iitc_task,
+      ci.id AS iitc_r_id,
+      ci.first AS iitc_r_first,
+      ci.last AS iitc_r_last,
       io.id AS juse_r_id,
       io.first AS juse_r_first,
       io.last AS juse_r_last

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/main/resources/org/apache/aurora/scheduler/storage/db/schema.sql
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/storage/db/schema.sql b/src/main/resources/org/apache/aurora/scheduler/storage/db/schema.sql
index a450a09..866e658 100644
--- a/src/main/resources/org/apache/aurora/scheduler/storage/db/schema.sql
+++ b/src/main/resources/org/apache/aurora/scheduler/storage/db/schema.sql
@@ -99,7 +99,6 @@ CREATE TABLE job_updates(
   job_key_id BIGINT NOT NULL REFERENCES job_keys(id),
   update_id VARCHAR NOT NULL,
   user VARCHAR NOT NULL,
-  instance_count INT NOT NULL,
   update_group_size INT NOT NULL,
   max_per_instance_failures INT NOT NULL,
   max_failed_instances INT NOT NULL,
@@ -135,6 +134,15 @@ CREATE TABLE job_updates_to_instance_overrides(
   UNIQUE(update_id, first, last)
 );
 
+CREATE TABLE job_updates_to_desired_instances(
+  id IDENTITY,
+  update_id BIGINT NOT NULL REFERENCES job_updates(id) ON DELETE CASCADE,
+  first INT NOT NULL,
+  last INT NOT NULL,
+
+  UNIQUE(update_id, first, last)
+);
+
 CREATE TABLE job_update_configs_to_instances(
   id IDENTITY,
   config_id BIGINT NOT NULL REFERENCES job_update_configs(id) ON DELETE CASCADE,

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/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
index 9f1a28c..2376a5e 100644
--- a/src/main/thrift/org/apache/aurora/gen/api.thrift
+++ b/src/main/thrift/org/apache/aurora/gen/api.thrift
@@ -658,18 +658,15 @@ struct JobUpdateSummary {
 }
 
 /** Update configuration and setting details. */
-struct JobUpdateConfiguration {
+struct JobUpdateInstructions {
   /** Actual InstanceId -> TaskConfig mapping when the update was requested. */
-  1: set<InstanceTaskConfig> oldTaskConfigs
+  1: set<InstanceTaskConfig> initialState
 
-  /** Desired TaskConfig when the update completes. */
-  2: TaskConfig newTaskConfig
-
-  /** Desired instance count when the update completes. */
-  3: i32 instanceCount
+  /** Desired configuration when the update completes. */
+  2: InstanceTaskConfig desiredState
 
   /** Update specific settings. */
-  4: JobUpdateSettings settings
+  3: JobUpdateSettings settings
 }
 
 /** Full definition of the job update. */
@@ -678,7 +675,7 @@ struct JobUpdate {
   1: JobUpdateSummary summary
 
   /** Update configuration. */
-  2: JobUpdateConfiguration configuration
+  2: JobUpdateInstructions instructions
 }
 
 struct JobUpdateDetails {

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java b/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
index 5a974cf..9041b42 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
@@ -27,9 +27,9 @@ import org.apache.aurora.gen.InstanceTaskConfig;
 import org.apache.aurora.gen.JobInstanceUpdateEvent;
 import org.apache.aurora.gen.JobUpdate;
 import org.apache.aurora.gen.JobUpdateAction;
-import org.apache.aurora.gen.JobUpdateConfiguration;
 import org.apache.aurora.gen.JobUpdateDetails;
 import org.apache.aurora.gen.JobUpdateEvent;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateQuery;
 import org.apache.aurora.gen.JobUpdateSettings;
 import org.apache.aurora.gen.JobUpdateState;
@@ -49,9 +49,9 @@ import org.apache.aurora.scheduler.storage.Storage.Work.Quiet;
 import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
 import org.apache.aurora.scheduler.storage.entities.ILock;
@@ -102,13 +102,22 @@ public class DBJobUpdateStoreTest {
     assertUpdate(update2);
   }
 
+  @Test(expected = StorageException.class)
+  public void testSaveWithEmptyDesiredStateInstancesThrows() {
+    JobUpdate builder = makeJobUpdate(JOB, "u1").newBuilder();
+    builder.getInstructions().getDesiredState().setInstances(ImmutableSet.<Range>of());
+
+    // Save with empty desired state instances.
+    saveUpdate(IJobUpdate.build(builder), "lock");
+  }
+
   @Test
   public void testSaveJobUpdateEmptyInstanceOverrides() {
     String updateId = "u1";
 
     IJobUpdate update = makeJobUpdate(JOB, updateId);
     JobUpdate builder = update.newBuilder();
-    builder.getConfiguration().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
+    builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
 
     IJobUpdate expected = IJobUpdate.build(builder);
 
@@ -123,12 +132,12 @@ public class DBJobUpdateStoreTest {
 
     IJobUpdate update = makeJobUpdate(JOB, updateId);
     JobUpdate builder = update.newBuilder();
-    builder.getConfiguration().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
+    builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
 
     IJobUpdate expected = IJobUpdate.build(builder);
 
     // Save with null overrides.
-    builder.getConfiguration().getSettings().setUpdateOnlyTheseInstances(null);
+    builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(null);
     saveUpdate(IJobUpdate.build(builder), "lock");
     assertUpdate(expected);
   }
@@ -481,10 +490,10 @@ public class DBJobUpdateStoreTest {
 
     IJobUpdate update = makeJobUpdate(JobKeys.from("role", "env", "name1"), updateId);
 
-    assertEquals(Optional.<IJobUpdate>absent(), getUpdateConfiguration(updateId));
+    assertEquals(Optional.<IJobUpdateInstructions>absent(), getUpdateInstructions(updateId));
 
     saveUpdate(update, "lock1");
-    assertEquals(Optional.of(makeJobUpdateConfiguration()), getUpdateConfiguration(updateId));
+    assertEquals(Optional.of(makeJobUpdateInstructions()), getUpdateInstructions(updateId));
   }
 
   private void assertUpdate(IJobUpdate expected) {
@@ -502,11 +511,11 @@ public class DBJobUpdateStoreTest {
     });
   }
 
-  private Optional<IJobUpdateConfiguration> getUpdateConfiguration(final String updateId) {
-    return storage.consistentRead(new Quiet<Optional<IJobUpdateConfiguration>>() {
+  private Optional<IJobUpdateInstructions> getUpdateInstructions(final String updateId) {
+    return storage.consistentRead(new Quiet<Optional<IJobUpdateInstructions>>() {
       @Override
-      public Optional<IJobUpdateConfiguration> apply(Storage.StoreProvider storeProvider) {
-        return storeProvider.getJobUpdateStore().fetchJobUpdateConfiguration(updateId);
+      public Optional<IJobUpdateInstructions> apply(Storage.StoreProvider storeProvider) {
+        return storeProvider.getJobUpdateStore().fetchJobUpdateInstructions(updateId);
       }
     });
   }
@@ -681,14 +690,15 @@ public class DBJobUpdateStoreTest {
 
   private IJobUpdate makeJobUpdate() {
     return IJobUpdate.build(new JobUpdate()
-        .setConfiguration(makeJobUpdateConfiguration().newBuilder()));
+        .setInstructions(makeJobUpdateInstructions().newBuilder()));
   }
 
-  private IJobUpdateConfiguration makeJobUpdateConfiguration() {
-    return IJobUpdateConfiguration.build(new JobUpdateConfiguration()
-        .setNewTaskConfig(makeTaskConfig())
-        .setInstanceCount(8)
-        .setOldTaskConfigs(ImmutableSet.of(
+  private IJobUpdateInstructions makeJobUpdateInstructions() {
+    return IJobUpdateInstructions.build(new JobUpdateInstructions()
+        .setDesiredState(new InstanceTaskConfig()
+            .setTask(makeTaskConfig())
+            .setInstances(ImmutableSet.of(new Range(0, 7), new Range(8, 9))))
+        .setInitialState(ImmutableSet.of(
             new InstanceTaskConfig()
                 .setInstances(ImmutableSet.of(new Range(0, 1), new Range(2, 3)))
                 .setTask(makeTaskConfig()),

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/storage/log/LogStorageTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/log/LogStorageTest.java b/src/test/java/org/apache/aurora/scheduler/storage/log/LogStorageTest.java
index b1d79a6..ccc2f68 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/log/LogStorageTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/log/LogStorageTest.java
@@ -38,8 +38,8 @@ import org.apache.aurora.gen.JobConfiguration;
 import org.apache.aurora.gen.JobInstanceUpdateEvent;
 import org.apache.aurora.gen.JobUpdate;
 import org.apache.aurora.gen.JobUpdateAction;
-import org.apache.aurora.gen.JobUpdateConfiguration;
 import org.apache.aurora.gen.JobUpdateEvent;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateSettings;
 import org.apache.aurora.gen.JobUpdateStatus;
 import org.apache.aurora.gen.JobUpdateSummary;
@@ -756,10 +756,11 @@ public class LogStorageTest extends EasyMockTest {
             .setUpdateId(UPDATE_ID)
             .setJobKey(JOB_KEY.newBuilder())
             .setUser("user"))
-        .setConfiguration(new JobUpdateConfiguration()
-            .setNewTaskConfig(new TaskConfig())
-            .setInstanceCount(4)
-            .setOldTaskConfigs(ImmutableSet.of(new InstanceTaskConfig()
+        .setInstructions(new JobUpdateInstructions()
+            .setDesiredState(new InstanceTaskConfig()
+                .setTask(new TaskConfig())
+                .setInstances(ImmutableSet.of(new Range(0, 3))))
+            .setInitialState(ImmutableSet.of(new InstanceTaskConfig()
                 .setTask(new TaskConfig())
                 .setInstances(ImmutableSet.of(new Range(0, 3)))))
             .setSettings(new JobUpdateSettings())));

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java b/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
index 7d4dd37..336cada 100644
--- a/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
@@ -66,8 +66,8 @@ import org.apache.aurora.gen.JobStats;
 import org.apache.aurora.gen.JobSummary;
 import org.apache.aurora.gen.JobSummaryResult;
 import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateConfiguration;
 import org.apache.aurora.gen.JobUpdateDetails;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateQuery;
 import org.apache.aurora.gen.JobUpdateRequest;
 import org.apache.aurora.gen.JobUpdateSettings;
@@ -126,6 +126,7 @@ import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
 import org.apache.aurora.scheduler.storage.entities.ILock;
 import org.apache.aurora.scheduler.storage.entities.ILockKey;
+import org.apache.aurora.scheduler.storage.entities.IRange;
 import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
 import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
 import org.apache.aurora.scheduler.storage.entities.IServerInfo;
@@ -2293,12 +2294,22 @@ public class SchedulerThriftInterfaceTest extends EasyMockTest {
         .setTaskConfig(config);
   }
 
+  private static Integer rangesToInstanceCount(Set<IRange> ranges) {
+    int instanceCount = 0;
+    for (IRange range : ranges) {
+      instanceCount += range.getLast() - range.getFirst() + 1;
+    }
+
+    return instanceCount;
+  }
+
   private static JobUpdateRequest buildJobUpdateRequest(IJobUpdate update) {
     return new JobUpdateRequest()
-        .setInstanceCount(update.getConfiguration().getInstanceCount())
+        .setInstanceCount(rangesToInstanceCount(
+            update.getInstructions().getDesiredState().getInstances()))
         .setJobKey(update.getSummary().getJobKey().newBuilder())
-        .setSettings(update.getConfiguration().getSettings().newBuilder())
-        .setTaskConfig(update.getConfiguration().getNewTaskConfig().newBuilder());
+        .setSettings(update.getInstructions().getSettings().newBuilder())
+        .setTaskConfig(update.getInstructions().getDesiredState().getTask().newBuilder());
   }
 
   private static IJobUpdate buildJobUpdate(
@@ -2316,10 +2327,11 @@ public class SchedulerThriftInterfaceTest extends EasyMockTest {
             .setJobKey(JOB_KEY.newBuilder())
             .setUpdateId(UPDATE_ID)
             .setUser(ROLE_IDENTITY.getUser()))
-        .setConfiguration(new JobUpdateConfiguration()
+        .setInstructions(new JobUpdateInstructions()
             .setSettings(new JobUpdateSettings())
-            .setInstanceCount(instanceCount)
-            .setNewTaskConfig(newConfig.newBuilder())
-            .setOldTaskConfigs(builder.build())));
+            .setDesiredState(new InstanceTaskConfig()
+                .setTask(newConfig.newBuilder())
+                .setInstances(ImmutableSet.of(new Range(0, instanceCount - 1))))
+            .setInitialState(builder.build())));
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/updater/AddTaskTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/updater/AddTaskTest.java b/src/test/java/org/apache/aurora/scheduler/updater/AddTaskTest.java
index 1b8e5c2..f9ed46f 100644
--- a/src/test/java/org/apache/aurora/scheduler/updater/AddTaskTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/updater/AddTaskTest.java
@@ -16,20 +16,20 @@ package org.apache.aurora.scheduler.updater;
 import com.twitter.common.testing.easymock.EasyMockTest;
 
 import org.apache.aurora.gen.InstanceKey;
-import org.apache.aurora.gen.JobUpdateConfiguration;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateSettings;
 import org.apache.aurora.gen.JobUpdateStatus;
 import org.apache.aurora.scheduler.base.JobKeys;
 import org.apache.aurora.scheduler.state.StateManager;
 import org.apache.aurora.scheduler.storage.TaskStore;
 import org.apache.aurora.scheduler.storage.entities.IInstanceKey;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.junit.Before;
 import org.junit.Test;
 
 public class AddTaskTest extends EasyMockTest {
-  private static final IJobUpdateConfiguration CONFIG = IJobUpdateConfiguration.build(
-      new JobUpdateConfiguration()
+  private static final IJobUpdateInstructions INSTRUCTIONS = IJobUpdateInstructions.build(
+      new JobUpdateInstructions()
           .setSettings(
               new JobUpdateSettings()
                   .setMinWaitInInstanceRunningMs(1000)));
@@ -53,7 +53,7 @@ public class AddTaskTest extends EasyMockTest {
 
     handler.getReevaluationDelay(
         INSTANCE,
-        CONFIG,
+        INSTRUCTIONS,
         taskStore,
         stateManager,
         JobUpdateStatus.ROLLING_BACK);

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java b/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
index 0e15a79..061d7e7 100644
--- a/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
@@ -40,8 +40,8 @@ import org.apache.aurora.gen.ExecutorConfig;
 import org.apache.aurora.gen.Identity;
 import org.apache.aurora.gen.InstanceTaskConfig;
 import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateConfiguration;
 import org.apache.aurora.gen.JobUpdateEvent;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateSettings;
 import org.apache.aurora.gen.JobUpdateStatus;
 import org.apache.aurora.gen.JobUpdateSummary;
@@ -238,7 +238,7 @@ public class JobUpdaterIT extends EasyMockTest {
   }
 
   private void insertInitialTasks(IJobUpdate update) {
-    for (IInstanceTaskConfig config : update.getConfiguration().getOldTaskConfigs()) {
+    for (IInstanceTaskConfig config : update.getInstructions().getInitialState()) {
       stateManager.insertPendingTasks(config.getTask(), expandInstanceIds(ImmutableSet.of(config)));
     }
   }
@@ -309,7 +309,7 @@ public class JobUpdaterIT extends EasyMockTest {
 
     JobUpdate builder =
         setInstanceCount(makeJobUpdate(makeInstanceConfig(0, 1, OLD_CONFIG)), 1).newBuilder();
-    builder.getConfiguration().getSettings().setUpdateOnlyTheseInstances(
+    builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(
         ImmutableSet.of(new Range(0, 0)));
     IJobUpdate update = IJobUpdate.build(builder);
     insertInitialTasks(update);
@@ -483,23 +483,24 @@ public class JobUpdaterIT extends EasyMockTest {
     control.replay();
 
     JobUpdate update = makeJobUpdate().newBuilder();
-    update.getConfiguration().getSettings().setUpdateGroupSize(-1);
+    update.getInstructions().getSettings().setUpdateGroupSize(-1);
     expectInvalid(update);
 
     update = makeJobUpdate().newBuilder();
-    update.getConfiguration().getSettings().setMaxWaitToInstanceRunningMs(0);
+    update.getInstructions().getSettings().setMaxWaitToInstanceRunningMs(0);
     expectInvalid(update);
 
     update = makeJobUpdate().newBuilder();
-    update.getConfiguration().getSettings().setMinWaitInInstanceRunningMs(0);
+    update.getInstructions().getSettings().setMinWaitInInstanceRunningMs(0);
     expectInvalid(update);
 
     update = makeJobUpdate().newBuilder();
-    update.getConfiguration().setInstanceCount(0);
+    update.getInstructions().setDesiredState(
+        new InstanceTaskConfig().setInstances(ImmutableSet.<Range>of()));
     expectInvalid(update);
 
     update = makeJobUpdate().newBuilder();
-    update.getConfiguration().getSettings().addToUpdateOnlyTheseInstances(new Range(0, 100));
+    update.getInstructions().getSettings().addToUpdateOnlyTheseInstances(new Range(0, 100));
     try {
       updater.start(IJobUpdate.build(update), USER);
       fail();
@@ -535,7 +536,7 @@ public class JobUpdaterIT extends EasyMockTest {
         store.deleteAllUpdatesAndEvents();
 
         JobUpdate builder = update.newBuilder();
-        builder.getConfiguration().setInstanceCount(0);
+        builder.getInstructions().getSettings().setUpdateGroupSize(0);
         for (ILock lock : lockManager.getLocks()) {
           lockManager.releaseLock(lock);
         }
@@ -713,9 +714,10 @@ public class JobUpdaterIT extends EasyMockTest {
   private static IJobUpdate makeJobUpdate(IInstanceTaskConfig... configs) {
     JobUpdate builder = new JobUpdate()
         .setSummary(makeUpdateSummary().newBuilder())
-        .setConfiguration(new JobUpdateConfiguration()
-            .setNewTaskConfig(NEW_CONFIG.newBuilder())
-            .setInstanceCount(3)
+        .setInstructions(new JobUpdateInstructions()
+            .setDesiredState(new InstanceTaskConfig()
+                .setTask(NEW_CONFIG.newBuilder())
+                .setInstances(ImmutableSet.of(new Range(0, 2))))
             .setSettings(new JobUpdateSettings()
                 .setUpdateGroupSize(1)
                 .setMaxWaitToInstanceRunningMs(RUNNING_TIMEOUT.as(Time.MILLISECONDS).intValue())
@@ -723,7 +725,7 @@ public class JobUpdaterIT extends EasyMockTest {
                 .setUpdateOnlyTheseInstances(ImmutableSet.<Range>of())));
 
     for (IInstanceTaskConfig config : configs) {
-      builder.getConfiguration().addToOldTaskConfigs(config.newBuilder());
+      builder.getInstructions().addToInitialState(config.newBuilder());
     }
 
     return IJobUpdate.build(builder);
@@ -731,7 +733,8 @@ public class JobUpdaterIT extends EasyMockTest {
 
   private static IJobUpdate setInstanceCount(IJobUpdate update, int instanceCount) {
     JobUpdate builder = update.newBuilder();
-    builder.getConfiguration().setInstanceCount(instanceCount);
+    builder.getInstructions().getDesiredState().setInstances(
+        ImmutableSet.of(new Range(0, instanceCount - 1)));
     return IJobUpdate.build(builder);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/java/org/apache/aurora/scheduler/updater/UpdateFactoryImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/updater/UpdateFactoryImplTest.java b/src/test/java/org/apache/aurora/scheduler/updater/UpdateFactoryImplTest.java
index f698b53..548d315 100644
--- a/src/test/java/org/apache/aurora/scheduler/updater/UpdateFactoryImplTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/updater/UpdateFactoryImplTest.java
@@ -17,11 +17,11 @@ import com.google.common.collect.ImmutableSet;
 import com.twitter.common.util.testing.FakeClock;
 
 import org.apache.aurora.gen.InstanceTaskConfig;
-import org.apache.aurora.gen.JobUpdateConfiguration;
+import org.apache.aurora.gen.JobUpdateInstructions;
 import org.apache.aurora.gen.JobUpdateSettings;
 import org.apache.aurora.gen.Range;
 import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateConfiguration;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -34,13 +34,14 @@ import static org.junit.Assert.assertEquals;
  */
 public class UpdateFactoryImplTest {
 
-  private static final IJobUpdateConfiguration CONFIG = IJobUpdateConfiguration.build(
-      new JobUpdateConfiguration()
-          .setNewTaskConfig(new TaskConfig())
-          .setInstanceCount(3)
-          .setOldTaskConfigs(ImmutableSet.of(new InstanceTaskConfig()
-              .setInstances(ImmutableSet.of(new Range(1, 2)))
-              .setTask(new TaskConfig())))
+  private static final IJobUpdateInstructions INSTRUCTIONS = IJobUpdateInstructions.build(
+      new JobUpdateInstructions()
+          .setDesiredState(new InstanceTaskConfig()
+              .setTask(new TaskConfig())
+              .setInstances(ImmutableSet.of(new Range(0, 2))))
+          .setInitialState(ImmutableSet.of(new InstanceTaskConfig()
+              .setTask(new TaskConfig())
+              .setInstances(ImmutableSet.of(new Range(1, 2)))))
           .setSettings(new JobUpdateSettings()
               .setMaxFailedInstances(1)
               .setMaxPerInstanceFailures(1)
@@ -58,48 +59,48 @@ public class UpdateFactoryImplTest {
 
   @Test
   public void testRollingForward() throws Exception  {
-    Update update = factory.newUpdate(CONFIG, true);
+    Update update = factory.newUpdate(INSTRUCTIONS, true);
     assertEquals(ImmutableSet.of(0, 1, 2), update.getUpdater().getInstances());
   }
 
   @Test
   public void testRollingBack() throws Exception {
-    Update update = factory.newUpdate(CONFIG, false);
+    Update update = factory.newUpdate(INSTRUCTIONS, false);
     assertEquals(ImmutableSet.of(0, 1, 2), update.getUpdater().getInstances());
   }
 
   @Test
   public void testRollForwardSpecificInstances() throws Exception {
-    JobUpdateConfiguration config = CONFIG.newBuilder();
+    JobUpdateInstructions config = INSTRUCTIONS.newBuilder();
     config.getSettings().setUpdateOnlyTheseInstances(ImmutableSet.of(new Range(1, 2)));
 
-    Update update = factory.newUpdate(IJobUpdateConfiguration.build(config), true);
+    Update update = factory.newUpdate(IJobUpdateInstructions.build(config), true);
     assertEquals(ImmutableSet.of(1, 2), update.getUpdater().getInstances());
   }
 
   @Test
   public void testRollBackSpecificInstances() throws Exception {
-    JobUpdateConfiguration config = CONFIG.newBuilder();
+    JobUpdateInstructions config = INSTRUCTIONS.newBuilder();
     config.getSettings().setUpdateOnlyTheseInstances(ImmutableSet.of(new Range(1, 2)));
 
-    Update update = factory.newUpdate(IJobUpdateConfiguration.build(config), false);
+    Update update = factory.newUpdate(IJobUpdateInstructions.build(config), false);
     assertEquals(ImmutableSet.of(1, 2), update.getUpdater().getInstances());
   }
 
   @Test(expected = UpdateConfigurationException.class)
   public void testInvalidConfiguration() throws Exception {
-    JobUpdateConfiguration config = CONFIG.newBuilder();
+    JobUpdateInstructions config = INSTRUCTIONS.newBuilder();
     config.getSettings().setUpdateOnlyTheseInstances(ImmutableSet.of(new Range(10, 10)));
 
-    factory.newUpdate(IJobUpdateConfiguration.build(config), true);
+    factory.newUpdate(IJobUpdateInstructions.build(config), true);
   }
 
   @Test
   public void testUpdateRemovesInstance() throws Exception {
-    JobUpdateConfiguration config = CONFIG.newBuilder();
-    config.setInstanceCount(2);
+    JobUpdateInstructions config = INSTRUCTIONS.newBuilder();
+    config.getDesiredState().setInstances(ImmutableSet.of(new Range(0, 1)));
 
-    Update update = factory.newUpdate(IJobUpdateConfiguration.build(config), true);
+    Update update = factory.newUpdate(IJobUpdateInstructions.build(config), true);
     assertEquals(ImmutableSet.of(0, 1, 2), update.getUpdater().getInstances());
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/860dc4e9/src/test/resources/org/apache/aurora/gen/api.thrift.md5
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/aurora/gen/api.thrift.md5 b/src/test/resources/org/apache/aurora/gen/api.thrift.md5
index c583876..e2bea71 100644
--- a/src/test/resources/org/apache/aurora/gen/api.thrift.md5
+++ b/src/test/resources/org/apache/aurora/gen/api.thrift.md5
@@ -1 +1 @@
-a93c06b77f8984f5cab81cf3d6c4c4c2
+20d3ee1ae2debf847cfb322b882abdcf


Mime
View raw message