Repository: brooklyn-server
Updated Branches:
  refs/heads/master 97a922d6c -> c3d71a2e9


BROOKLYN-602: fix config key order for yaml overrides


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/eafd8d04
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/eafd8d04
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/eafd8d04

Branch: refs/heads/master
Commit: eafd8d047f0746c953ebc42385c332591a515ecc
Parents: 97a922d
Author: Aled Sage <aled.s...@gmail.com>
Authored: Mon Oct 1 15:49:20 2018 +0100
Committer: Aled Sage <aled.s...@gmail.com>
Committed: Tue Oct 2 09:22:24 2018 +0100

----------------------------------------------------------------------
 .../camp/brooklyn/ConfigParametersYamlTest.java | 65 +++++++++++++++
 .../brooklyn/core/objs/BasicSpecParameter.java  | 10 ++-
 .../resources/BundleAndTypeResourcesTest.java   | 86 ++++++++++++++++++++
 3 files changed, 159 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/eafd8d04/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
----------------------------------------------------------------------
diff --git 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
index 7770270..5f277ee 100644
--- 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
+++ 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
@@ -29,13 +29,17 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
+import org.apache.brooklyn.api.catalog.CatalogConfig;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.entity.ImplementedBy;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.catalog.SpecParameterUnwrappingTest;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
@@ -49,6 +53,7 @@ import org.apache.brooklyn.core.entity.Dumper;
 import org.apache.brooklyn.core.location.PortRanges;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
 import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
 import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
 import org.apache.brooklyn.entity.stock.BasicApplication;
@@ -1194,6 +1199,66 @@ public class ConfigParametersYamlTest extends 
AbstractYamlRebindTest {
         }
     }
 
+    @Test
+    public void testConfigParameterPinnedOrder() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  version: " + TEST_VERSION,
+                "  itemType: entity",
+                "  items:",
+                "    - id: entity-without-keys",
+                "      item:",
+                "        type: "+TestEntityWithPinnedConfig.class.getName(),
+                "    - id: entity-with-keys-redeclared",
+                "      item:",
+                "        type: "+TestEntityWithPinnedConfig.class.getName(),
+                "        brooklyn.parameters:",
+                "          - name: pinned2",
+                "          - name: unpinned2");
+
+        for (String symbolicName : ImmutableList.of("entity-without-keys", 
"entity-with-keys-redeclared")) {
+            // Mimicking the code in REST api's TypeResource, for getting the 
config keys
+            RegisteredType item = mgmt().getTypeRegistry().get(symbolicName, 
TEST_VERSION);
+            AbstractBrooklynObjectSpec<?, ?> spec = 
mgmt().getTypeRegistry().createSpec(item, null, null);
+            List<SpecParameter<?>> params = spec.getParameters();
+            SpecParameter<?> pinned2 = Iterables.find(params, (p) -> 
p.getConfigKey().getName().equals("pinned2"));
+            SpecParameter<?> unpinned2 = Iterables.find(params, (p) -> 
p.getConfigKey().getName().equals("unpinned2"));
+            
+            assertEquals(pinned2.getLabel(), "mylabel-pinned2", 
"item="+symbolicName);
+            assertEquals(pinned2.isPinned(), true, "item="+symbolicName);
+            
+            assertEquals(unpinned2.getLabel(), "mylabel-unpinned2", 
"item="+symbolicName);
+            assertEquals(unpinned2.isPinned(), false, "item="+symbolicName);
+            
+            List<String> keys = params.stream().map((p) -> 
p.getConfigKey().getName()).collect(Collectors.toList());
+            assertEquals(keys.subList(0, 6), ImmutableList.of("pinned1", 
"pinned2", "pinned3", "unpinned1", "unpinned2", "unpinned3"), 
"item="+symbolicName+"; actual="+keys);
+        }
+    }
+    
+    @ImplementedBy(TestEntityWithPinnedConfigImpl.class)
+    public static interface TestEntityWithPinnedConfig extends Entity {
+        
+        @CatalogConfig(label="pinned1", pinned=true, priority=6)
+        public static final ConfigKey<String> P1 = 
ConfigKeys.builder(String.class).name("pinned1").build();
+        
+        @CatalogConfig(label="mylabel-pinned2", pinned=true, priority=5)
+        public static final ConfigKey<String> P2 = 
ConfigKeys.builder(String.class).name("pinned2").build();
+        
+        @CatalogConfig(label="pinned3", pinned=true, priority=4)
+        public static final ConfigKey<String> P3 = 
ConfigKeys.builder(String.class).name("pinned3").build();
+        
+        @CatalogConfig(label="unpinned1", pinned=false, priority=3)
+        public static final ConfigKey<String> UNP1 = 
ConfigKeys.builder(String.class).name("unpinned1").build();
+        
+        @CatalogConfig(label="mylabel-unpinned2", pinned=false, priority=2)
+        public static final ConfigKey<String> UNP2 = 
ConfigKeys.builder(String.class).name("unpinned2").build();
+        
+        @CatalogConfig(label="unpinned3", pinned=false, priority=1)
+        public static final ConfigKey<String> UNP3 = 
ConfigKeys.builder(String.class).name("unpinned3").build();
+    }
+    public static class TestEntityWithPinnedConfigImpl extends TestEntityImpl 
implements TestEntityWithPinnedConfig {
+    }
+    
     protected <T> void assertKeyEquals(Entity entity, String keyName, String 
expectedDescription, Class<T> expectedType, T expectedDefaultVal, T 
expectedEntityVal) {
         ConfigKey<?> key = entity.getEntityType().getConfigKey(keyName);
         assertNotNull(key, "No key '"+keyName+"'; 
keys="+entity.getEntityType().getConfigKeys());

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/eafd8d04/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java 
b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
index 7c777f8..b2c24aa 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
@@ -485,7 +485,8 @@ public class BasicSpecParameter<T> implements 
SpecParameter<T>{
 
         if (newParams!=null) {
             for (SpecParameter<?> p: newParams) {
-                final SpecParameter<?> existingP = 
existingToKeep.remove(p.getConfigKey().getName());
+                // Don't remove + add, as that changes order: see 
https://issues.apache.org/jira/browse/BROOKLYN-602
+                final SpecParameter<?> existingP = 
existingToKeep.get(p.getConfigKey().getName());
                 if (p instanceof 
SpecParameterIncludingDefinitionForInheritance) {
                     // config keys should be transformed to parameters and so 
should be found;
                     // so the code below is correct whether existingP is set 
or is null 
@@ -494,7 +495,12 @@ public class BasicSpecParameter<T> implements 
SpecParameter<T>{
                     // shouldn't happen; all calling logic should get 
SpecParameterForInheritance;
                     log.warn("Found non-definitional spec parameter: "+p+" 
adding to "+spec);
                 }
-                result.add(p);
+                
+                if (existingP != null) {
+                    existingToKeep.put(p.getConfigKey().getName(), p);
+                } else {
+                    result.add(p);
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/eafd8d04/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/BundleAndTypeResourcesTest.java
----------------------------------------------------------------------
diff --git 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/BundleAndTypeResourcesTest.java
 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/BundleAndTypeResourcesTest.java
index de9977c..8406dcd 100644
--- 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/BundleAndTypeResourcesTest.java
+++ 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/BundleAndTypeResourcesTest.java
@@ -44,7 +44,9 @@ import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import org.apache.brooklyn.api.catalog.CatalogConfig;
 import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ImplementedBy;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.Configurable;
 import org.apache.brooklyn.api.objs.Identifiable;
@@ -52,11 +54,14 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.EntityPredicates;
 import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiStandaloneTest;
 import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
 import org.apache.brooklyn.enricher.stock.Aggregator;
 import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy;
 import org.apache.brooklyn.rest.domain.BundleInstallationRestResult;
@@ -1373,4 +1378,85 @@ public class BundleAndTypeResourcesTest extends 
BrooklynRestResourceTest {
         Assert.assertEquals(entity2r, entity2);
     }
     
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testConfigKeyOrdering() {
+        String symbolicNameSimple = "my-catalog-item";
+        String symbolicNameRedeclaringKeys = 
"my-catalog-item-redeclaring-keys";
+        
+        ImmutableList<Map<?, ?>> expectedConfigOrdering = ImmutableList.of(
+                ImmutableMap.of("name", "unp2", "label", "unp 2", "pinned", 
false),
+                ImmutableMap.of("name", "unp3", "label", "unp 3", "pinned", 
false),
+                ImmutableMap.of("name", "unp1", "label", "unp 1", "pinned", 
false),
+                ImmutableMap.of("name", "p2", "label", "p 2", "pinned", true, 
"priority", 1.0D),
+                ImmutableMap.of("name", "p3", "label", "p 3", "pinned", true, 
"priority", 2.0D),
+                ImmutableMap.of("name", "p1", "label", "p 1", "pinned", true, 
"priority", 3.0D));
+        
+        String yaml = Joiner.on("\n").join(
+                        "brooklyn.catalog:",
+                        "  version: " + TEST_VERSION,
+                        "  itemType: entity",
+                        "  items:",
+                        "    - id: " + symbolicNameSimple,
+                        "      item:",
+                        "        type: " + 
TestEntityWithPinnedConfig.class.getName(),
+                        "    - id: " + symbolicNameRedeclaringKeys,
+                        "      item:",
+                        "        type: " + 
TestEntityWithPinnedConfig.class.getName(),
+                        "        brooklyn.parameters:",
+                        "          - name: unp2",
+                        "          - name: unp1",
+                        "          - name: p2",
+                        "          - name: p1");
+                
+        Response response = client().path("/catalog/bundles")
+                .header(HttpHeaders.CONTENT_TYPE, "application/yaml")
+                .post(yaml);
+        assertEquals(response.getStatus(), 
Response.Status.CREATED.getStatusCode());
+
+        for (String symbolicName : ImmutableList.of(symbolicNameSimple, 
symbolicNameRedeclaringKeys)) {
+            TypeDetail entityItem = 
client().path("/catalog/types/"+symbolicName + "/" + TEST_VERSION)
+                    .get(TypeDetail.class);
+            
+            List<Map<?,?>> entityConfig = (List<Map<?, ?>>) 
entityItem.getExtraFields().get("config");
+            
+            assertInitialConfigOrdering("item="+symbolicName, entityConfig, 
expectedConfigOrdering);
+        }
+    }
+    
+    private void assertInitialConfigOrdering(String context, List<Map<?, ?>> 
actuals, List<Map<?, ?>> expecteds) {
+        String actualsStr = "\n\t" + Joiner.on("\n\t").join(actuals);
+        int index = 0;
+        for (int i = 0; i < expecteds.size(); i++) {
+            Map<?, ?> actual = actuals.get(i);
+            Map<?, ?> expected = expecteds.get(i);
+            for (Map.Entry<?, ?> entry : expected.entrySet()) {
+                assertEquals(actual.get(entry.getKey()), entry.getValue(), 
"context="+context+"; index="+index+"; actual="+actual+"; actuals="+actualsStr);
+            }
+        }
+    }
+
+    @ImplementedBy(TestEntityWithPinnedConfigImpl.class)
+    public static interface TestEntityWithPinnedConfig extends Entity {
+        
+        @CatalogConfig(label="p 1", pinned=true, priority=1)
+        public static final ConfigKey<String> P1 = 
ConfigKeys.builder(String.class).name("p1").build();
+        
+        @CatalogConfig(label="p 2", pinned=true, priority=3)
+        public static final ConfigKey<String> P2 = 
ConfigKeys.builder(String.class).name("p2").build();
+        
+        @CatalogConfig(label="p 3", pinned=true, priority=2)
+        public static final ConfigKey<String> P3 = 
ConfigKeys.builder(String.class).name("p3").build();
+        
+        @CatalogConfig(label="unp 1", pinned=false, priority=4)
+        public static final ConfigKey<String> UNP1 = 
ConfigKeys.builder(String.class).name("unp1").build();
+        
+        @CatalogConfig(label="unp 2", pinned=false, priority=6)
+        public static final ConfigKey<String> UNP2 = 
ConfigKeys.builder(String.class).name("unp2").build();
+        
+        @CatalogConfig(label="unp 3", pinned=false, priority=5)
+        public static final ConfigKey<String> UNP3 = 
ConfigKeys.builder(String.class).name("unp3").build();
+    }
+    public static class TestEntityWithPinnedConfigImpl extends TestEntityImpl 
implements TestEntityWithPinnedConfig {
+    }
 }

Reply via email to