blob: 66d3cfee922055d89bd95bb4227414c1f2a98cba [file] [log] [blame]
/*
* 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;
}
}
}