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 5f277eec97..5db4601154 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 @@ -1181,6 +1181,46 @@ public void testConfigParameterConstraintObject() throws Exception { assertKeyEquals(newEntity, "testRequired", null, String.class, null, "myprefix-myVal"); } + @Test + public void testConfigParameterConstraintOnOtherKeyWithAttributeWhenReady() throws Exception { + addCatalogItems( + "brooklyn.catalog:", + " itemType: entity", + " items:", + " - id: entity-with-keys", + " item:", + " type: "+TestEntity.class.getName(), + " brooklyn.parameters:", + " - name: key1", + " type: String", + " constraints:", + " - requiredUnless: key2", + " - name: key2", + " type: String", + " constraints:", + " - requiredUnless: key1"); + + String yaml = Joiner.on("\n").join( + "services:", + "- type: entity-with-keys", + " brooklyn.config:", + " key1: $brooklyn:root().attributeWhenReady(\"myattribute\")"); + + Entity app = createStartWaitAndLogApplication(yaml); + TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren()); + + Predicate constraint = entity.getEntityType().getConfigKey("key1").getConstraint(); + assertEquals(constraint.toString(), "requiredUnless(\"key2\")"); + + // Rebind, and then check again that the config key is listed + Entity newApp = rebind(); + TestEntity newEntity = (TestEntity) Iterables.getOnlyElement(newApp.getChildren()); + + Predicate newConstraint = newEntity.getEntityType().getConfigKey("key1").getConstraint(); + assertEquals(newConstraint.toString(), "requiredUnless(\"key2\")"); + } + + public static class PredicateRegexPojo implements Predicate { private String regex; diff --git a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java index b0ed3f8271..bcc9a25e3a 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java @@ -300,7 +300,17 @@ public boolean apply(Object input, BrooklynObject context) { // would be nice to offer an explanation, but that will need a richer API or a thread local List vals = new ArrayList<>(); for (String otherKeyName : otherKeyNames) { - vals.add(context.config().get(ConfigKeys.newConfigKey(Object.class, otherKeyName))); + // Use getNonBlocking, in case the value is an `attributeWhenReady` and the + // attribute is not yet available - don't want to hang. + ConfigKey otherKey = ConfigKeys.newConfigKey(Object.class, otherKeyName); + BrooklynObjectInternal.ConfigurationSupportInternal configInternal = ((BrooklynObjectInternal) context).config(); + + Maybe maybeValue = configInternal.getNonBlocking(otherKey); + if (maybeValue.isPresent()) { + vals.add(maybeValue.get()); + } else { + return true; // abort; assume valid + } } return test(input, vals); }