| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.brooklyn.camp.brooklyn; |
| |
| import static org.testng.Assert.assertEquals; |
| import static org.testng.Assert.fail; |
| |
| import java.io.StringReader; |
| import java.util.Map; |
| |
| import org.apache.brooklyn.api.catalog.CatalogItem; |
| import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; |
| import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType; |
| import org.apache.brooklyn.api.entity.Entity; |
| import org.apache.brooklyn.api.mgmt.ExecutionContext; |
| import org.apache.brooklyn.api.mgmt.ManagementContext; |
| import org.apache.brooklyn.config.ConfigKey; |
| import org.apache.brooklyn.core.config.ConfigKeys; |
| import org.apache.brooklyn.core.config.external.AbstractExternalConfigSupplier; |
| import org.apache.brooklyn.core.config.external.ExternalConfigSupplier; |
| import org.apache.brooklyn.core.internal.BrooklynProperties; |
| import org.apache.brooklyn.core.location.cloud.CloudLocationConfig; |
| import org.apache.brooklyn.core.mgmt.internal.CampYamlParser; |
| import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; |
| import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; |
| import org.apache.brooklyn.core.test.entity.TestApplication; |
| import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; |
| import org.apache.brooklyn.util.core.task.DeferredSupplier; |
| import org.apache.brooklyn.util.core.task.Tasks; |
| import org.apache.brooklyn.util.exceptions.Exceptions; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.testng.annotations.Test; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.Iterables; |
| |
| @Test |
| public class ExternalConfigYamlTest extends AbstractYamlTest { |
| private static final Logger log = LoggerFactory.getLogger(ExternalConfigYamlTest.class); |
| |
| // Choose a small jar; it is downloaded in some tests. |
| // Pick an OSGi bundle that is not part of core brooklyn. |
| private static final String LIBRARY_URL = "https://repository.apache.org/content/groups/public/org/apache/logging/log4j/log4j-api/2.5/log4j-api-2.5.jar"; |
| private static final String LIBRARY_SYMBOLIC_NAME = "org.apache.logging.log4j.api"; |
| private static final String LIBRARY_VERSION = "2.5.0"; |
| |
| @Override |
| protected LocalManagementContext newTestManagementContext() { |
| BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); |
| props.put("brooklyn.external.myprovider", MyExternalConfigSupplier.class.getName()); |
| props.put("brooklyn.external.myprovider.mykey", "myval"); |
| props.put("brooklyn.external.myproviderWithoutMapArg", MyExternalConfigSupplierWithoutMapArg.class.getName()); |
| |
| props.put("brooklyn.external.myprovider.myCatalogId", "myId"); |
| props.put("brooklyn.external.myprovider.myCatalogItemType", "template"); |
| props.put("brooklyn.external.myprovider.myCatalogVersion", "1.2"); |
| props.put("brooklyn.external.myprovider.myCatalogDescription", "myDescription"); |
| props.put("brooklyn.external.myprovider.myCatalogDisplayName", "myDisplayName"); |
| props.put("brooklyn.external.myprovider.myCatalogIconUrl", "classpath:///myIconUrl.png"); |
| props.put("brooklyn.external.myprovider.myCatalogLibraryUrl", LIBRARY_URL); |
| props.put("brooklyn.external.myprovider.myCatalogLibraryName", LIBRARY_SYMBOLIC_NAME); |
| props.put("brooklyn.external.myprovider.myCatalogLibraryVersion", LIBRARY_VERSION); |
| |
| return LocalManagementContextForTests.builder(true) |
| .useProperties(props) |
| .disableOsgi(false) |
| .build(); |
| } |
| |
| @Test |
| public void testCampYamlParserHandlesExternalisedConfig() throws Exception { |
| CampYamlParser parser = mgmt().getConfig().getConfig(CampYamlParser.YAML_PARSER_KEY); |
| |
| DeferredSupplier<?> supplier = (DeferredSupplier<?>) parser.parse("$brooklyn:external(\"myprovider\", \"mykey\")"); |
| |
| ExecutionContext exec = mgmt().getServerExecutionContext(); |
| String result = Tasks.resolveValue(supplier, String.class, exec); |
| assertEquals(result, "myval"); |
| } |
| |
| @Test |
| public void testExternalisedConfigReferencedFromYaml() throws Exception { |
| ConfigKey<String> MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key"); |
| |
| String yaml = Joiner.on("\n").join( |
| "services:", |
| "- serviceType: org.apache.brooklyn.core.test.entity.TestApplication", |
| " brooklyn.config:", |
| " my.config.key: $brooklyn:external(\"myprovider\", \"mykey\")"); |
| |
| TestApplication app = (TestApplication) createAndStartApplication(new StringReader(yaml)); |
| waitForApplicationTasks(app); |
| |
| assertEquals(app.getConfig(MY_CONFIG_KEY), "myval"); |
| } |
| |
| @Test |
| public void testExternalisedLocationConfigReferencedFromYaml() throws Exception { |
| ConfigKey<String> MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key"); |
| |
| String yaml = Joiner.on("\n").join( |
| "services:", |
| "- type: org.apache.brooklyn.core.test.entity.TestApplication", |
| "location:", |
| " localhost:", |
| " my.config.key: $brooklyn:external(\"myprovider\", \"mykey\")"); |
| |
| TestApplication app = (TestApplication) createAndStartApplication(new StringReader(yaml)); |
| waitForApplicationTasks(app); |
| assertEquals(Iterables.getOnlyElement( app.getLocations() ).config().get(MY_CONFIG_KEY), "myval"); |
| } |
| |
| // Will download the given catalog library jar |
| @Test(groups="Integration") |
| public void testExternalisedCatalogConfigReferencedFromYaml() throws Exception { |
| String yaml = Joiner.on("\n").join( |
| "brooklyn.catalog:", |
| " id: $brooklyn:external(\"myprovider\", \"myCatalogId\")", |
| " itemType: $brooklyn:external(\"myprovider\", \"myCatalogItemType\")", |
| " version: $brooklyn:external(\"myprovider\", \"myCatalogVersion\")", |
| " description: $brooklyn:external(\"myprovider\", \"myCatalogDescription\")", |
| " displayName: $brooklyn:external(\"myprovider\", \"myCatalogDisplayName\")", |
| " iconUrl: $brooklyn:external(\"myprovider\", \"myCatalogIconUrl\")", |
| " brooklyn.libraries:", |
| " - $brooklyn:external(\"myprovider\", \"myCatalogLibraryUrl\")", |
| "", |
| " item:", |
| " services:", |
| " - type: brooklyn.entity.database.mysql.MySqlNode"); |
| |
| catalog.addItems(yaml); |
| |
| CatalogItem<Object, Object> item = Iterables.getOnlyElement(catalog.getCatalogItems()); |
| CatalogBundle bundle = Iterables.getOnlyElement(item.getLibraries()); |
| assertEquals(item.getId(), "myId:1.2"); |
| assertEquals(item.getCatalogItemType(), CatalogItemType.TEMPLATE); |
| assertEquals(item.getVersion(), "1.2"); |
| assertEquals(item.getDescription(), "myDescription"); |
| assertEquals(item.getDisplayName(), "myDisplayName"); |
| assertEquals(item.getIconUrl(), "classpath:///myIconUrl.png"); |
| assertEquals(bundle.getUrl(), LIBRARY_URL); |
| } |
| |
| // Will download the given catalog library jar |
| @Test(groups="Integration") |
| public void testExternalisedCatalogConfigReferencedFromYamlWithLibraryMap() throws Exception { |
| String yaml = Joiner.on("\n").join( |
| "brooklyn.catalog:", |
| " id: myid", |
| " itemType: template", |
| " version: 1.2", |
| " description: myDescription", |
| " displayName: myDisplayName", |
| " iconUrl: classpath:///myIconUrl.png", |
| " brooklyn.libraries:", |
| " - name: $brooklyn:external(\"myprovider\", \"myCatalogLibraryName\")", |
| " version: $brooklyn:external(\"myprovider\", \"myCatalogLibraryVersion\")", |
| " url: $brooklyn:external(\"myprovider\", \"myCatalogLibraryUrl\")", |
| "", |
| " item:", |
| " services:", |
| " - type: brooklyn.entity.database.mysql.MySqlNode"); |
| |
| catalog.addItems(yaml); |
| |
| CatalogItem<Object, Object> item = Iterables.getOnlyElement(catalog.getCatalogItems()); |
| CatalogBundle bundle = Iterables.getOnlyElement(item.getLibraries()); |
| assertEquals(bundle.getUrl(), LIBRARY_URL); |
| assertEquals(bundle.getSymbolicName(), LIBRARY_SYMBOLIC_NAME); |
| assertEquals(bundle.getVersion(), LIBRARY_VERSION); |
| } |
| |
| // Will download the given catalog library jar |
| // Confirms "normal" behaviour, when all values in the catalog are hard-coded rather than using external config. |
| @Test(groups="Integration") |
| public void testNonExternalisedCatalogConfigReferencedFromYaml() throws Exception { |
| String yaml = Joiner.on("\n").join( |
| "brooklyn.catalog:", |
| " id: osgi.test", |
| " itemType: template", |
| " version: 1.3", |
| " description: CentOS 6.6 With GUI - 1.3", |
| " displayName: CentOS 6.6", |
| " iconUrl: classpath:///centos.png", |
| " brooklyn.libraries:", |
| " - " + LIBRARY_URL, |
| "", |
| " item:", |
| " services:", |
| " - type: brooklyn.entity.database.mysql.MySqlNode"); |
| |
| catalog.addItems(yaml); |
| |
| CatalogItem<Object, Object> item = Iterables.getOnlyElement(catalog.getCatalogItems()); |
| assertEquals(item.getId(), "osgi.test:1.3"); |
| assertEquals(item.getCatalogItemType(), CatalogItemType.TEMPLATE); |
| assertEquals(item.getVersion(), "1.3"); |
| assertEquals(item.getDescription(), "CentOS 6.6 With GUI - 1.3"); |
| assertEquals(item.getDisplayName(), "CentOS 6.6"); |
| assertEquals(item.getIconUrl(), "classpath:///centos.png"); |
| assertEquals(Iterables.getOnlyElement(item.getLibraries()).getUrl(), LIBRARY_URL); |
| } |
| |
| @Test(groups="Integration") |
| public void testExternalisedLocationConfigSetViaProvisioningPropertiesReferencedFromYaml() throws Exception { |
| String yaml = Joiner.on("\n").join( |
| "services:", |
| "- type: "+EmptySoftwareProcess.class.getName(), |
| " provisioning.properties:", |
| " credential: $brooklyn:external(\"myprovider\", \"mykey\")", |
| "location: localhost"); |
| |
| Entity app = createAndStartApplication(new StringReader(yaml)); |
| waitForApplicationTasks(app); |
| Entity entity = Iterables.getOnlyElement( app.getChildren() ); |
| assertEquals(Iterables.getOnlyElement( entity.getLocations() ).config().get(CloudLocationConfig.ACCESS_CREDENTIAL), "myval"); |
| } |
| |
| @Test |
| public void testExternalisedConfigFromSupplierWithoutMapArg() throws Exception { |
| ConfigKey<String> MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key"); |
| |
| String yaml = Joiner.on("\n").join( |
| "services:", |
| "- serviceType: org.apache.brooklyn.core.test.entity.TestApplication", |
| " brooklyn.config:", |
| " my.config.key: $brooklyn:external(\"myproviderWithoutMapArg\", \"mykey\")"); |
| |
| TestApplication app = (TestApplication) createAndStartApplication(new StringReader(yaml)); |
| waitForApplicationTasks(app); |
| |
| assertEquals(app.getConfig(MY_CONFIG_KEY), "myHardcodedVal"); |
| } |
| |
| @Test |
| public void testWhenExternalisedConfigSupplierDoesNotExist() throws Exception { |
| BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); |
| props.put("brooklyn.external.myprovider", "wrong.classname.DoesNotExist"); |
| |
| try { |
| LocalManagementContextForTests.builder(true) |
| .useProperties(props) |
| .build(); |
| fail(); |
| } catch (Exception e) { |
| if (Exceptions.getFirstThrowableOfType(e, ClassNotFoundException.class) == null) { |
| throw e; |
| } |
| } |
| } |
| |
| @Test |
| public void testWhenExternalisedConfigSupplierDoesNotHavingRightConstructor() throws Exception { |
| BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); |
| props.put("brooklyn.external.myprovider", MyExternalConfigSupplierWithWrongConstructor.class.getName()); |
| |
| try { |
| LocalManagementContext mgmt2 = LocalManagementContextForTests.builder(true) |
| .useProperties(props) |
| .build(); |
| mgmt2.terminate(); |
| fail(); |
| } catch (Exception e) { |
| if (!e.toString().contains("No matching constructor")) { |
| throw e; |
| } |
| } |
| } |
| |
| @Override |
| protected Logger getLogger() { |
| return log; |
| } |
| |
| public static class MyExternalConfigSupplier extends AbstractExternalConfigSupplier { |
| private final Map<String, String> conf; |
| |
| public MyExternalConfigSupplier(ManagementContext mgmt, String name, Map<String, String> conf) { |
| super(mgmt, name); |
| this.conf = conf; |
| } |
| |
| @Override public String get(String key) { |
| return conf.get(key); |
| } |
| } |
| |
| public static class MyExternalConfigSupplierWithoutMapArg extends AbstractExternalConfigSupplier { |
| public MyExternalConfigSupplierWithoutMapArg(ManagementContext mgmt, String name) { |
| super(mgmt, name); |
| } |
| |
| @Override public String get(String key) { |
| return key.equals("mykey") ? "myHardcodedVal" : null; |
| } |
| } |
| |
| public static class MyExternalConfigSupplierWithWrongConstructor implements ExternalConfigSupplier { |
| public MyExternalConfigSupplierWithWrongConstructor(double d) { |
| } |
| |
| @Override public String getName() { |
| return "myname"; |
| } |
| |
| @Override public String get(String key) { |
| return null; |
| } |
| } |
| |
| } |