Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
import java.util.Collection;
import java.util.NoSuchElementException;

import javax.annotation.Nullable;

import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
import org.apache.brooklyn.api.typereg.ManagedBundle;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;

Expand Down Expand Up @@ -111,12 +115,17 @@ public interface BrooklynCatalog {
CatalogItem<?,?> addItem(String yaml, boolean forceUpdate);

/**
* Adds items (represented in yaml) to the catalog.
* Fails if the same version exists in catalog.
* As {@link #addItemsFromBundle(String, ManagedBundle)} with a null bundle.
*/
Iterable<? extends CatalogItem<?,?>> addItems(String yaml);

/**
* Adds items (represented in yaml) to the catalog coming from the indicated managed bundle.
* Fails if the same version exists in catalog (unless snapshot).
*
* @throws IllegalArgumentException if the yaml was invalid
*/
Iterable<? extends CatalogItem<?,?>> addItems(String yaml);
Iterable<? extends CatalogItem<?,?>> addItems(String yaml, @Nullable ManagedBundle definingBundle);

/**
* Adds items (represented in yaml) to the catalog.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ public static interface CatalogItemLibraries {
@Nullable public String getIconUrl();

public String getSymbolicName();

public String getContainingBundle();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not make this a VersionedName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done this and a commit, but then reverted it. I'm not sure everything comes from a bundle just yet. When it does we can reinstate. To me it is tied up with use of search paths etc.


public String getVersion();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
import org.apache.brooklyn.api.objs.BrooklynObject;
import org.apache.brooklyn.util.osgi.VersionedName;

/** Describes an OSGi bundle which Brooklyn manages, including persisting */
public interface ManagedBundle extends BrooklynObject, Rebindable, OsgiBundleWithUrl {
Expand All @@ -29,4 +30,6 @@ public interface ManagedBundle extends BrooklynObject, Rebindable, OsgiBundleWit
* This typically includes the unique {@link #getId()} of this item. */
String getOsgiUniqueUrl();

VersionedName getVersionedName();

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public interface RegisteredType extends Identifiable {

String getSymbolicName();
String getVersion();
/** Bundle in symbolicname:id format where this type is defined */
// TODO would prefer this to be VersionedName if/when everything comes from OSGi bundles
// unrevert 7260bf9cf3f3ebaaa790693e1b7217a81bef78a7 to start that, and adjust serialization
// as described in that commit message (supporting String in xstream serialization for VN)
String getContainingBundle();

Collection<OsgiBundleWithUrl> getLibraries();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ public <T extends Entity> EntitySpec<T> resolveSpec(Set<String> encounteredRegis
// TODO propagate exception so we can provide better error messages
msgDetails = "The reference " + type + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but couldn't load it (missing or invalid syntax?). " +
"It's also neither a catalog item nor a java type.";
} else if ("brooklyn".equals(proto)){
msgDetails = "The reference " + type + " is not a registered catalog item nor a java type.";
} else {
msgDetails = "The reference " + type + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but the protocol " +
proto + " isn't white listed (" + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + "). " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,19 @@
import org.apache.brooklyn.core.catalog.internal.CatalogBomScanner;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.typereg.BasicManagedBundle;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.core.osgi.BundleMaker;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.osgi.VersionedName;
import org.apache.brooklyn.util.text.Identifiers;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
Expand Down Expand Up @@ -89,7 +91,8 @@ public void cleanUpButKeepMgmt() throws Exception {
Entities.destroy(app);
}
for (Bundle b: bundlesToRemove) {
b.uninstall();
((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(
((ManagementContextInternal)mgmt()).getOsgiManager().get().getManagedBundle(new VersionedName(b)));
}
bundlesToRemove.clear();
}
Expand Down Expand Up @@ -156,7 +159,8 @@ public void testCatalogBomFromBundleWithManualManifest() throws Exception {

jf = bm.copyAddingManifest(jf, MutableMap.of(
"Manifest-Version", "1.0",
"Bundle-SymbolicName", customName));
"Bundle-SymbolicName", customName,
"Bundle-Version", "0.0.0.SNAPSHOT"));

Assert.assertTrue(bm.hasOsgiManifest(jf));

Expand All @@ -172,10 +176,8 @@ public void testCatalogBomFromBundleWithManualManifest() throws Exception {

private void installBundle(File jf) {
try (FileInputStream fin = new FileInputStream(jf)) {
BasicManagedBundle bundleMetadata = new BasicManagedBundle();
Bundle bundle =
((LocalManagementContext)mgmt()).getOsgiManager().get().installUploadedBundle(bundleMetadata, fin, true);
bundlesToRemove.add(bundle);
OsgiBundleInstallationResult br = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(fin).get();
bundlesToRemove.add(br.getBundle());
} catch (Exception e) {
throw Exceptions.propagate(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ public void testLibraryUrlDoesNotExist() throws Exception {
" - type: " + BasicApplication.class.getName());
Asserts.shouldHaveFailedPreviously();
} catch (Exception e) {
if (!e.toString().contains("Bundle from " + wrongUrl + " failed to install")) {
throw e;
}
Asserts.expectedFailureContains(e, wrongUrl);
Asserts.expectedFailureContainsIgnoreCase(e, "not found");
}
}

Expand All @@ -199,9 +198,7 @@ public void testLibraryMalformed() throws Exception {
" - type: " + BasicApplication.class.getName());
Asserts.shouldHaveFailedPreviously();
} catch (Exception e) {
if (!e.toString().contains("not a jar file")) {
throw e;
}
Asserts.expectedFailureContainsIgnoreCase(e, "opening zip");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,23 @@
import org.apache.brooklyn.api.typereg.ManagedBundle;
import org.apache.brooklyn.api.typereg.RegisteredType;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
import org.apache.brooklyn.core.effector.Effectors;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.StartableApplication;
import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.typereg.BasicManagedBundle;
import org.apache.brooklyn.entity.stock.BasicApplication;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.support.TestResourceUnavailableException;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.osgi.OsgiTestResources;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
Expand All @@ -66,8 +70,8 @@ protected boolean useOsgi() {
@Test
public void testRebindAppIncludingBundle() throws Exception {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_COM_EXAMPLE_PATH);
((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(new BasicManagedBundle(),
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL), true);
((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL) );

createAndStartApplication("services: [ { type: "+BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY+" } ]");

Expand Down Expand Up @@ -198,4 +202,113 @@ public void testEffectorInBundleReferencedByStockCatalogItem() throws Exception
Effector<?> newEffector = newEntity.getEntityType().getEffectorByName("myEffector").get();
newEntity.invoke(newEffector, ImmutableMap.<String, Object>of()).get();
}

@Test
public void testClassAccessAfterUninstall() throws Exception {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH);

// install dependency
((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL) );

// now the v2 bundle
OsgiBundleInstallationResult b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL) ).get();

Assert.assertEquals(b.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");

String yaml = Strings.lines("name: simple-app-yaml",
"services:",
"- type: " + BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
Entity app = createAndStartApplication(yaml);
Entity more = Iterables.getOnlyElement( app.getChildren() );

Assert.assertEquals(
more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Bob")).get(),
"HI BOB FROM V2");

((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(b.getMetadata());
Assert.assertEquals(b.getBundle().getState(), Bundle.UNINSTALLED);

// can still call things
Assert.assertEquals(
more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Claudia")).get(),
"HI CLAUDIA FROM V2");

// but still uninstalled, and attempt to create makes error
Assert.assertEquals(b.getBundle().getState(), Bundle.UNINSTALLED);
try {
Entity app2 = createAndStartApplication(yaml);
Asserts.shouldHaveFailedPreviously("Expected deployment to fail after uninstall; instead got "+app2);
} catch (Exception e) {
Asserts.expectedFailureContainsIgnoreCase(e, "unable to match", BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
}

try {
StartableApplication app2 = rebind();
Asserts.shouldHaveFailedPreviously("Expected deployment to fail rebind; instead got "+app2);
} catch (Exception e) {
// should fail to rebind this entity
Asserts.expectedFailureContainsIgnoreCase(e, more.getId(), "unable to load", BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
}
}

@Test
public void testClassAccessAfterUpgrade() throws Exception {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH);

// install dependency
((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL) ).checkNoError();

// now the v2 bundle
OsgiBundleInstallationResult b2a = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL) ).get();

Assert.assertEquals(b2a.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");
Assert.assertEquals(b2a.getCode(), OsgiBundleInstallationResult.ResultCode.INSTALLED_NEW_BUNDLE);

String yaml = Strings.lines("name: simple-app-yaml",
"services:",
"- type: " + BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
Entity app = createAndStartApplication(yaml);
Entity more = Iterables.getOnlyElement( app.getChildren() );

Assert.assertEquals(
more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Bob")).get(),
"HI BOB FROM V2");

// unforced upgrade should report already installed
Assert.assertEquals( ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL) ).get().getCode(),
OsgiBundleInstallationResult.ResultCode.IGNORING_BUNDLE_AREADY_INSTALLED);

// force upgrade
OsgiBundleInstallationResult b2b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(b2a.getMetadata(),
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL), true, true, true).get();
Assert.assertEquals(b2a.getBundle(), b2b.getBundle());
Assert.assertEquals(b2b.getCode(), OsgiBundleInstallationResult.ResultCode.UPDATED_EXISTING_BUNDLE);

// calls to things previously instantiated get the old behaviour
Assert.assertEquals(
more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Claudia")).get(),
"HI CLAUDIA FROM V2");

// but new deployment gets the new behaviour
StartableApplication app2 = (StartableApplication) createAndStartApplication(yaml);
Entity more2 = Iterables.getOnlyElement( app2.getChildren() );
Assert.assertEquals(
more2.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Daphne")).get(),
"HO DAPHNE FROM V2 EVIL TWIN");
app2.stop();

// and after rebind on the old we get new behaviour
StartableApplication app1 = rebind();
Entity more1 = Iterables.getOnlyElement( app1.getChildren() );
Assert.assertEquals(
more1.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Eric")).get(),
"HO ERIC FROM V2 EVIL TWIN");
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@
import org.apache.brooklyn.api.typereg.RegisteredType;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
import org.apache.brooklyn.core.objs.BrooklynTypes;
import org.apache.brooklyn.core.typereg.BasicManagedBundle;
import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
import org.apache.brooklyn.core.typereg.RegisteredTypes;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.support.TestResourceUnavailableException;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.osgi.OsgiTestResources;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
Expand All @@ -69,19 +69,19 @@ private static String getLocalResource(String filename) {

@Test
public void testBrooklynManagedBundleInstall() throws Exception {
BasicManagedBundle mb = new BasicManagedBundle();
Bundle b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(mb,
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL), true);
Assert.assertEquals(mb.getSymbolicName(), b.getSymbolicName());
OsgiBundleInstallationResult br = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL) ).get();
Assert.assertEquals(br.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.1.0");

// bundle installed
Map<String, ManagedBundle> bundles = ((ManagementContextInternal)mgmt()).getOsgiManager().get().getManagedBundles();
Asserts.assertSize(bundles.keySet(), 1);
Assert.assertEquals(mb.getId(), Iterables.getOnlyElement( bundles.keySet() ));
Assert.assertEquals(br.getMetadata().getId(), Iterables.getOnlyElement( bundles.keySet() ));

// types installed
RegisteredType t = mgmt().getTypeRegistry().get(BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
Assert.assertNotNull(t);
Assert.assertEquals(t.getContainingBundle(), br.getVersionedName().toString());

// can deploy
createAndStartApplication("services: [ { type: "+BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY+" } ]");
Expand Down Expand Up @@ -181,7 +181,8 @@ public void testMoreEntityV1ThenV2GivesV2() throws Exception {
OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
}

@Test
@Test(groups="Broken") // won't work until search path is based on bundles instead of registered types
// (though it would work if we set versions properly in the OSGi bundles, but brooklyn types there all declare brooklyn version)
public void testMoreEntityBothV1AndV2() throws Exception {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
Expand Down
Loading