Remove resource properties from ResourceAggregate

Bugs closed: AURORA-1975

Reviewed at https://reviews.apache.org/r/67077/
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 0ef75d6..5cb6959 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -29,6 +29,7 @@
   SLA-aware drain of the tasks, before marking the host as `DRAINED`. So maintenance requests
   survive across scheduler fail-overs. Use the newly introduced `aurora_admin sla_host_drain`
   to skip the SLA computations on the admin client.
+- Removed resource fields (`numCpus`, `ramMb`, `diskMb`) from ResourceAggregate.
 
 0.20.0
 ======
diff --git a/api/src/main/thrift/org/apache/aurora/gen/api.thrift b/api/src/main/thrift/org/apache/aurora/gen/api.thrift
index 54007c8..7265b11 100644
--- a/api/src/main/thrift/org/apache/aurora/gen/api.thrift
+++ b/api/src/main/thrift/org/apache/aurora/gen/api.thrift
@@ -320,15 +320,6 @@
 }
 
 struct ResourceAggregate {
-  // TODO(maxim): Deprecated. See AURORA-1707.
-  /** Number of CPU cores allotted. */
-  1: double numCpus
-  // TODO(maxim): Deprecated. See AURORA-1707.
-  /** Megabytes of RAM allotted. */
-  2: i64 ramMb
-  // TODO(maxim): Deprecated. See AURORA-1707.
-  /** Megabytes of disk space allotted. */
-  3: i64 diskMb
   /** Aggregated resource values. */
   4: set<Resource> resources
 }
diff --git a/src/main/java/org/apache/aurora/scheduler/http/Quotas.java b/src/main/java/org/apache/aurora/scheduler/http/Quotas.java
index aa68c44..fd63ddd 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/Quotas.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/Quotas.java
@@ -16,6 +16,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.ws.rs.GET;
@@ -29,10 +30,16 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 
+import org.apache.aurora.scheduler.resources.ResourceType;
 import org.apache.aurora.scheduler.storage.Storage;
+import org.apache.aurora.scheduler.storage.entities.IResource;
 import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
 import org.codehaus.jackson.annotate.JsonProperty;
 
+import static org.apache.aurora.scheduler.resources.ResourceType.CPUS;
+import static org.apache.aurora.scheduler.resources.ResourceType.DISK_MB;
+import static org.apache.aurora.scheduler.resources.ResourceType.RAM_MB;
+
 /**
  * Servlet that exposes allocated resource quotas.
  */
@@ -72,7 +79,18 @@
   }
 
   private static final Function<IResourceAggregate, ResourceAggregateBean> TO_BEAN =
-      quota -> new ResourceAggregateBean(quota.getNumCpus(), quota.getRamMb(), quota.getDiskMb());
+      quota -> new ResourceAggregateBean(
+          getResource(quota.getResources(), CPUS).getNumCpus(),
+          getResource(quota.getResources(), RAM_MB).getRamMb(),
+          getResource(quota.getResources(), DISK_MB).getDiskMb());
+
+  private static IResource getResource(Set<IResource> resources, ResourceType type) {
+    return resources.stream()
+        .filter(e -> ResourceType.fromResource(e).equals(type))
+        .findFirst()
+        .orElseThrow(() ->
+            new IllegalArgumentException("Missing resource definition for " + type));
+  }
 
   private static final class ResourceAggregateBean {
     private final double cpu;
diff --git a/src/main/java/org/apache/aurora/scheduler/quota/QuotaManager.java b/src/main/java/org/apache/aurora/scheduler/quota/QuotaManager.java
index e2750d7..19de66c 100644
--- a/src/main/java/org/apache/aurora/scheduler/quota/QuotaManager.java
+++ b/src/main/java/org/apache/aurora/scheduler/quota/QuotaManager.java
@@ -48,6 +48,7 @@
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
 import org.apache.aurora.scheduler.storage.entities.IRange;
+import org.apache.aurora.scheduler.storage.entities.IResource;
 import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
 import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
@@ -168,8 +169,12 @@
         final IResourceAggregate quota,
         MutableStoreProvider storeProvider) throws QuotaException {
 
-      if (quota.getNumCpus() < 0.0 || quota.getRamMb() < 0 || quota.getDiskMb() < 0) {
-        throw new QuotaException("Negative values in: " + quota.toString());
+      for (IResource resource : quota.getResources()) {
+        if (resource.isSetNumCpus() && resource.getNumCpus() < 0.0
+            || resource.isSetRamMb() && resource.getRamMb() < 0
+            || resource.isSetDiskMb() && resource.getDiskMb() < 0) {
+          throw new QuotaException("Negative values in: " + quota.toString());
+        }
       }
 
       QuotaInfo info = getQuotaInfo(ownerRole, Optional.empty(), storeProvider);
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfill.java b/src/main/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfill.java
index 4425d02..41a2f0b 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfill.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfill.java
@@ -23,7 +23,6 @@
 import org.apache.aurora.gen.JobConfiguration;
 import org.apache.aurora.gen.JobUpdate;
 import org.apache.aurora.gen.JobUpdateInstructions;
-import org.apache.aurora.gen.Resource;
 import org.apache.aurora.gen.ResourceAggregate;
 import org.apache.aurora.gen.ScheduledTask;
 import org.apache.aurora.gen.TaskConfig;
@@ -41,10 +40,6 @@
 import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
 
-import static org.apache.aurora.scheduler.resources.ResourceType.CPUS;
-import static org.apache.aurora.scheduler.resources.ResourceType.DISK_MB;
-import static org.apache.aurora.scheduler.resources.ResourceType.RAM_MB;
-
 /**
  * Helps migrating thrift schema by populating deprecated and/or replacement fields.
  */
@@ -57,14 +52,6 @@
     this.tierManager = requireNonNull(tierManager);
   }
 
-  private static Resource getResource(Set<Resource> resources, ResourceType type) {
-    return resources.stream()
-            .filter(e -> ResourceType.fromResource(IResource.build(e)).equals(type))
-            .findFirst()
-            .orElseThrow(() ->
-                    new IllegalArgumentException("Missing resource definition for " + type));
-  }
-
   /**
    * Ensures TaskConfig.resources and correspondent task-level fields are all populated.
    *
@@ -125,28 +112,16 @@
    * @return Backfilled IResourceAggregate.
    */
   public static IResourceAggregate backfillResourceAggregate(ResourceAggregate aggregate) {
-    if (!aggregate.isSetResources() || aggregate.getResources().isEmpty()) {
-      aggregate.addToResources(Resource.numCpus(aggregate.getNumCpus()));
-      aggregate.addToResources(Resource.ramMb(aggregate.getRamMb()));
-      aggregate.addToResources(Resource.diskMb(aggregate.getDiskMb()));
-    } else {
-      EnumSet<ResourceType> quotaResources = QuotaManager.QUOTA_RESOURCE_TYPES;
-      if (aggregate.getResources().size() > quotaResources.size()) {
-        throw new IllegalArgumentException("Too many resource values in quota.");
-      }
+    EnumSet<ResourceType> quotaResources = QuotaManager.QUOTA_RESOURCE_TYPES;
+    if (aggregate.getResources().size() > quotaResources.size()) {
+      throw new IllegalArgumentException("Too many resource values in quota.");
+    }
 
-      if (!quotaResources.equals(aggregate.getResources().stream()
-              .map(e -> ResourceType.fromResource(IResource.build(e)))
-              .collect(Collectors.toSet()))) {
+    if (!quotaResources.equals(aggregate.getResources().stream()
+        .map(e -> ResourceType.fromResource(IResource.build(e)))
+        .collect(Collectors.toSet()))) {
 
-        throw new IllegalArgumentException("Quota resources must be exactly: " + quotaResources);
-      }
-      aggregate.setNumCpus(
-              getResource(aggregate.getResources(), CPUS).getNumCpus());
-      aggregate.setRamMb(
-              getResource(aggregate.getResources(), RAM_MB).getRamMb());
-      aggregate.setDiskMb(
-              getResource(aggregate.getResources(), DISK_MB).getDiskMb());
+      throw new IllegalArgumentException("Quota resources must be exactly: " + quotaResources);
     }
     return IResourceAggregate.build(aggregate);
   }
diff --git a/src/main/python/apache/aurora/client/api/__init__.py b/src/main/python/apache/aurora/client/api/__init__.py
index f1a82cb..34822bc 100644
--- a/src/main/python/apache/aurora/client/api/__init__.py
+++ b/src/main/python/apache/aurora/client/api/__init__.py
@@ -329,7 +329,7 @@
               % (role, cpu, ram, disk))
     return self._scheduler_proxy.setQuota(
         role,
-        ResourceAggregate(cpu, ram, disk, frozenset([
+        ResourceAggregate(frozenset([
             Resource(numCpus=cpu),
             Resource(ramMb=ram),
             Resource(diskMb=disk)])))
diff --git a/src/main/python/apache/aurora/config/resource.py b/src/main/python/apache/aurora/config/resource.py
index b2ebd39..572205d 100644
--- a/src/main/python/apache/aurora/config/resource.py
+++ b/src/main/python/apache/aurora/config/resource.py
@@ -85,7 +85,7 @@
 
   @classmethod
   def resource_details_from_quota(cls, quota):
-    return cls.resource_details(cls._backfill_resources(quota))
+    return cls.resource_details(quota.resources)
 
   @classmethod
   def resource_details_from_task(cls, task):
diff --git a/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java b/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
index 567586f..07b4e43 100644
--- a/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
+++ b/src/test/java/org/apache/aurora/scheduler/resources/ResourceTestUtil.java
@@ -55,7 +55,7 @@
   }
 
   public static IResourceAggregate aggregate(double numCpus, long ramMb, long diskMb) {
-    return IResourceAggregate.build(new ResourceAggregate(numCpus, ramMb, diskMb, ImmutableSet.of(
+    return IResourceAggregate.build(new ResourceAggregate(ImmutableSet.of(
         numCpus(numCpus),
         ramMb(ramMb),
         diskMb(diskMb)
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/durability/DurableStorageTest.java b/src/test/java/org/apache/aurora/scheduler/storage/durability/DurableStorageTest.java
index fcca9a5..ddb9d06 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/durability/DurableStorageTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/durability/DurableStorageTest.java
@@ -220,16 +220,13 @@
     builder.add(Edit.op(Op.removeTasks(removeTasks)));
     storageUtil.taskStore.deleteTasks(removeTasks.getTaskIds());
 
-    ResourceAggregate nonBackfilled = new ResourceAggregate()
-        .setNumCpus(1.0)
-        .setRamMb(32)
-        .setDiskMb(64);
-    SaveQuota saveQuota = new SaveQuota(JOB_KEY.getRole(), nonBackfilled);
+    ResourceAggregate resourceAggregate = new ResourceAggregate()
+        .setResources(ImmutableSet.of(numCpus(1.0), ramMb(32), diskMb(64)));
+    SaveQuota saveQuota = new SaveQuota(JOB_KEY.getRole(), resourceAggregate);
     builder.add(Edit.op(Op.saveQuota(saveQuota)));
     storageUtil.quotaStore.saveQuota(
         saveQuota.getRole(),
-        IResourceAggregate.build(nonBackfilled.deepCopy()
-            .setResources(ImmutableSet.of(numCpus(1.0), ramMb(32), diskMb(64)))));
+        IResourceAggregate.build(resourceAggregate));
 
     builder.add(Edit.op(Op.removeQuota(new RemoveQuota(JOB_KEY.getRole()))));
     storageUtil.quotaStore.removeQuota(JOB_KEY.getRole());
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfillTest.java b/src/test/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfillTest.java
index 219576b..22131bd 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfillTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/durability/ThriftBackfillTest.java
@@ -21,7 +21,6 @@
 import org.apache.aurora.gen.TaskConfig;
 import org.apache.aurora.scheduler.TierManager;
 import org.apache.aurora.scheduler.base.TaskTestUtil;
-import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.junit.Before;
 import org.junit.Test;
@@ -65,36 +64,6 @@
         thriftBackfill.backfillTask(config));
   }
 
-  @Test
-  public void testResourceAggregateFieldsToSet() {
-    control.replay();
-
-    ResourceAggregate aggregate = new ResourceAggregate()
-        .setNumCpus(1.0)
-        .setRamMb(32)
-        .setDiskMb(64);
-
-    IResourceAggregate expected = IResourceAggregate.build(aggregate.deepCopy()
-        .setResources(ImmutableSet.of(numCpus(1.0), ramMb(32), diskMb(64))));
-
-    assertEquals(expected, ThriftBackfill.backfillResourceAggregate(aggregate));
-  }
-
-  @Test
-  public void testResourceAggregateSetToFields() {
-    control.replay();
-
-    ResourceAggregate aggregate = new ResourceAggregate()
-        .setResources(ImmutableSet.of(numCpus(1.0), ramMb(32), diskMb(64)));
-
-    IResourceAggregate expected = IResourceAggregate.build(aggregate.deepCopy()
-        .setNumCpus(1.0)
-        .setRamMb(32)
-        .setDiskMb(64));
-
-    assertEquals(expected, ThriftBackfill.backfillResourceAggregate(aggregate));
-  }
-
   @Test(expected = IllegalArgumentException.class)
   public void testResourceAggregateTooManyResources() {
     control.replay();
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 0fc3673..aa1cb2b 100644
--- a/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterfaceTest.java
@@ -730,13 +730,10 @@
   @Test
   public void testSetQuota() throws Exception {
     ResourceAggregate resourceAggregate = new ResourceAggregate()
-        .setNumCpus(10)
-        .setDiskMb(100)
-        .setRamMb(200);
+        .setResources(ImmutableSet.of(numCpus(10.0), ramMb(200), diskMb(100)));
     quotaManager.saveQuota(
         ROLE,
-        IResourceAggregate.build(resourceAggregate.deepCopy()
-            .setResources(ImmutableSet.of(numCpus(10), ramMb(200), diskMb(100)))),
+        IResourceAggregate.build(resourceAggregate),
         storageUtil.mutableStoreProvider);
 
     control.replay();
@@ -747,9 +744,7 @@
   @Test
   public void testSetQuotaFails() throws Exception {
     ResourceAggregate resourceAggregate = new ResourceAggregate()
-        .setNumCpus(10)
-        .setDiskMb(100)
-        .setRamMb(200);
+        .setResources(ImmutableSet.of(numCpus(10.0), ramMb(200), diskMb(100)));
     quotaManager.saveQuota(
         ROLE,
         IResourceAggregate.build(resourceAggregate.deepCopy()
diff --git a/src/test/python/apache/aurora/admin/test_admin.py b/src/test/python/apache/aurora/admin/test_admin.py
index ebe89b5..1c54d09 100644
--- a/src/test/python/apache/aurora/admin/test_admin.py
+++ b/src/test/python/apache/aurora/admin/test_admin.py
@@ -33,6 +33,7 @@
     AssignedTask,
     GetQuotaResult,
     JobKey,
+    Resource,
     ResourceAggregate,
     Response,
     ResponseCode,
@@ -194,9 +195,18 @@
       api = mock_make_admin_client.return_value
       role = 'test_role'
       api.get_quota.return_value = self.create_response(
-          ResourceAggregate(20.0, 4000, 6000),
-          ResourceAggregate(15.0, 2000, 3000),
-          ResourceAggregate(6.0, 200, 600),
+          ResourceAggregate(resources=frozenset([
+              Resource(numCpus=20.0),
+              Resource(ramMb=4000),
+              Resource(diskMb=6000)])),
+          ResourceAggregate(resources=frozenset([
+              Resource(numCpus=15.0),
+              Resource(ramMb=2000),
+              Resource(diskMb=3000)])),
+          ResourceAggregate(resources=frozenset([
+              Resource(numCpus=6.0),
+              Resource(ramMb=200),
+              Resource(diskMb=600)])),
       )
       api.set_quota.return_value = self.create_simple_success_response()
 
diff --git a/src/test/python/apache/aurora/client/cli/test_quota.py b/src/test/python/apache/aurora/client/cli/test_quota.py
index b566296..bf831bd 100644
--- a/src/test/python/apache/aurora/client/cli/test_quota.py
+++ b/src/test/python/apache/aurora/client/cli/test_quota.py
@@ -20,7 +20,7 @@
 
 from .util import AuroraClientCommandTest, FakeAuroraCommandContext
 
-from gen.apache.aurora.api.ttypes import GetQuotaResult, ResourceAggregate, Result
+from gen.apache.aurora.api.ttypes import GetQuotaResult, Resource, ResourceAggregate, Result
 
 
 class TestGetQuotaCommand(AuroraClientCommandTest):
@@ -29,7 +29,10 @@
     api = mock_context.get_api('west')
     response = cls.create_simple_success_response()
     response.result = Result(getQuotaResult=GetQuotaResult(
-        quota=ResourceAggregate(numCpus=5, ramMb=20480, diskMb=40960),
+        quota=ResourceAggregate(resources=frozenset([
+            Resource(numCpus=5),
+            Resource(ramMb=20480),
+            Resource(diskMb=40960)])),
         prodSharedConsumption=None,
         prodDedicatedConsumption=None,
         nonProdSharedConsumption=None,
@@ -42,11 +45,26 @@
     api = mock_context.get_api('west')
     response = cls.create_simple_success_response()
     response.result = Result(getQuotaResult=GetQuotaResult(
-      quota=ResourceAggregate(numCpus=5, ramMb=20480, diskMb=40960),
-      prodSharedConsumption=ResourceAggregate(numCpus=1, ramMb=512, diskMb=1024),
-      prodDedicatedConsumption=ResourceAggregate(numCpus=2, ramMb=1024, diskMb=2048),
-      nonProdSharedConsumption=ResourceAggregate(numCpus=3, ramMb=2048, diskMb=4096),
-      nonProdDedicatedConsumption=ResourceAggregate(numCpus=4, ramMb=4096, diskMb=8192),
+      quota=ResourceAggregate(resources=frozenset([
+          Resource(numCpus=5),
+          Resource(ramMb=20480),
+          Resource(diskMb=40960)])),
+      prodSharedConsumption=ResourceAggregate(resources=frozenset([
+          Resource(numCpus=1),
+          Resource(ramMb=512),
+          Resource(diskMb=1024)])),
+      prodDedicatedConsumption=ResourceAggregate(resources=frozenset([
+          Resource(numCpus=2),
+          Resource(ramMb=1024),
+          Resource(diskMb=2048)])),
+      nonProdSharedConsumption=ResourceAggregate(resources=frozenset([
+          Resource(numCpus=3),
+          Resource(ramMb=2048),
+          Resource(diskMb=4096)])),
+      nonProdDedicatedConsumption=ResourceAggregate(resources=frozenset([
+          Resource(numCpus=4),
+          Resource(ramMb=4096),
+          Resource(diskMb=8192)])),
     ))
     api.get_quota.return_value = response
 
@@ -67,18 +85,22 @@
     assert expected_output == self._get_quota(True, ['quota', 'get', 'west/bozo'])
 
   def test_get_quota_with_no_consumption_json(self):
-    assert (json.loads('{"quota":{"numCpus":5,"ramMb":20480,"diskMb":40960}}') ==
-            json.loads(self._get_quota(False, ['quota', 'get', '--write-json', 'west/bozo'])))
+    expected_response = self._response_converter(
+        (json.loads('{"quota":{"resources":[{"diskMb":40960},{"numCpus":5},{"ramMb":20480}]}}')))
+    actual_response = self._response_converter(
+        json.loads(self._get_quota(False, ['quota', 'get', '--write-json', 'west/bozo'])))
+    assert (expected_response == actual_response)
 
   def test_get_quota_with_consumption_json(self):
-    expected_response = json.loads(
-        '{"quota":{"numCpus":5,"ramMb":20480,"diskMb":40960},'
-        '"prodSharedConsumption":{"numCpus":1,"ramMb":512,"diskMb":1024},'
-        '"prodDedicatedConsumption":{"numCpus":2,"ramMb":1024,"diskMb":2048},'
-        '"nonProdSharedConsumption":{"numCpus":3,"ramMb":2048,"diskMb":4096},'
-        '"nonProdDedicatedConsumption":{"numCpus":4,"ramMb":4096,"diskMb":8192}}')
-    assert (expected_response ==
-            json.loads(self._get_quota(True, ['quota', 'get', '--write-json', 'west/bozo'])))
+    expected_response = self._response_converter(json.loads(
+        '{"quota":{"resources":[{"numCpus":5},{"ramMb":20480},{"diskMb":40960}]},'
+        '"prodSharedConsumption":{"resources":[{"numCpus":1},{"ramMb":512},{"diskMb":1024}]},'
+        '"prodDedicatedConsumption":{"resources":[{"numCpus":2},{"ramMb":1024},{"diskMb":2048}]},'
+        '"nonProdSharedConsumption":{"resources":[{"numCpus":3},{"ramMb":2048},{"diskMb":4096}]},'
+        '"nonProdDedicatedConsumption":{"resources":'
+        '[{"numCpus":4},{"ramMb":4096},{"diskMb":8192}]}}'))
+    assert (expected_response == self._response_converter(
+      json.loads(self._get_quota(True, ['quota', 'get', '--write-json', 'west/bozo']))))
 
   def test_get_quota_failed(self):
     fake_context = FakeAuroraCommandContext()
@@ -104,3 +126,13 @@
       cmd.execute(command_args)
       out = '\n'.join(mock_context.get_out())
       return out
+
+  def _response_converter(self, response):
+    resources_list = []
+    for key in response:
+      if 'resources' in response[key] and response[key]['resources'] is not None:
+        for resource in response[key]['resources']:
+          resources_list += resource.items()
+      response[key]['resources'] = sorted(resources_list, key=lambda x: (x[0], x[1]))
+      resources_list = []
+    return response
diff --git a/src/test/python/apache/aurora/config/test_resources.py b/src/test/python/apache/aurora/config/test_resources.py
index 3ac5490..988ab33 100644
--- a/src/test/python/apache/aurora/config/test_resources.py
+++ b/src/test/python/apache/aurora/config/test_resources.py
@@ -47,8 +47,11 @@
         ResourceType.CPUS)
     assert quantity == 1.0
 
-  def test_backfill_quota(self):
-    quota = ResourceAggregate(numCpus=1.0, ramMb=2, diskMb=3)
+  def test_quota(self):
+    quota = ResourceAggregate(resources={
+        Resource(numCpus=1.0),
+        Resource(ramMb=2),
+        Resource(diskMb=3)})
     assert ResourceManager.resource_details_from_quota(quota) == [
         ResourceDetails(ResourceType.CPUS, 1.0),
         ResourceDetails(ResourceType.RAM_MB, 2),
diff --git a/src/test/resources/org/apache/aurora/scheduler/storage/durability/goldens/current/saveQuota b/src/test/resources/org/apache/aurora/scheduler/storage/durability/goldens/current/saveQuota
index 6b0d800..e7aa38c 100644
--- a/src/test/resources/org/apache/aurora/scheduler/storage/durability/goldens/current/saveQuota
+++ b/src/test/resources/org/apache/aurora/scheduler/storage/durability/goldens/current/saveQuota
@@ -6,15 +6,6 @@
       },
       "2": {
         "rec": {
-          "1": {
-            "dbl": 8.0
-          },
-          "2": {
-            "i64": 4
-          },
-          "3": {
-            "i64": 4
-          },
           "4": {
             "set": [
               "rec",