use of co.cask.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class ArtifactHttpHandlerTest method testBatchProperties.
@Test
public void testBatchProperties() throws Exception {
ArtifactId wordcountId1 = NamespaceId.DEFAULT.artifact("wordcount", "1.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordcountId1), WordCountApp.class).getStatusLine().getStatusCode());
addArtifactProperties(Id.Artifact.fromEntityId(wordcountId1), ImmutableMap.of("k1", "v1", "k2", "v2"));
ArtifactId wordcountId2 = NamespaceId.DEFAULT.artifact("wc", "2.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordcountId2), WordCountApp.class).getStatusLine().getStatusCode());
addArtifactProperties(Id.Artifact.fromEntityId(wordcountId2), ImmutableMap.of("k2", "v20", "k3", "v30"));
List<String> props = ImmutableList.of("k1", "k2", "k3");
List<ArtifactPropertiesRequest> requestList = ImmutableList.of(new ArtifactPropertiesRequest(wordcountId1.getArtifact(), wordcountId1.getVersion(), ArtifactScope.USER, props), new ArtifactPropertiesRequest(wordcountId2.getArtifact(), wordcountId2.getVersion(), ArtifactScope.USER, props));
URL url = getEndPoint(String.format("%s/namespaces/%s/artifactproperties", Constants.Gateway.API_VERSION_3, NamespaceId.DEFAULT.getNamespace())).toURL();
HttpRequest request = HttpRequest.post(url).withBody(GSON.toJson(requestList)).build();
co.cask.common.http.HttpResponse response = HttpRequests.execute(request);
Assert.assertEquals(HttpResponseStatus.OK.code(), response.getResponseCode());
List<ArtifactSummaryProperties> actual = GSON.fromJson(response.getResponseBodyAsString(), new TypeToken<List<ArtifactSummaryProperties>>() {
}.getType());
List<ArtifactSummaryProperties> expected = ImmutableList.of(new ArtifactSummaryProperties(wordcountId1.getArtifact(), wordcountId1.getVersion(), ArtifactScope.USER, ImmutableMap.of("k1", "v1", "k2", "v2")), new ArtifactSummaryProperties(wordcountId2.getArtifact(), wordcountId2.getVersion(), ArtifactScope.USER, ImmutableMap.of("k2", "v20", "k3", "v30")));
Assert.assertEquals(expected, actual);
}
use of co.cask.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class ArtifactHttpHandlerTest method testPluginWithEndpoints.
@Test
public void testPluginWithEndpoints() throws Exception {
// add an app for plugins to extend
ArtifactId wordCount1Id = NamespaceId.DEFAULT.artifact("wordcount", "1.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordCount1Id), WordCountApp.class).getStatusLine().getStatusCode());
ArtifactId wordCount2Id = NamespaceId.DEFAULT.artifact("testartifact", "1.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordCount2Id), WordCountApp.class).getStatusLine().getStatusCode());
// add some plugins.
// plugins-3.0.0 extends wordcount[1.0.0,2.0.0)
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, CallablePlugin.class.getPackage().getName());
ArtifactId plugins3Id = NamespaceId.DEFAULT.artifact("plugins3", "1.0.0");
Set<ArtifactRange> plugins3Parents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(plugins3Id), CallablePlugin.class, manifest, plugins3Parents).getStatusLine().getStatusCode());
Set<PluginInfo> expectedInfos = Sets.newHashSet(new PluginInfo("CallablePlugin", "interactive", "This is plugin with endpoint", CallablePlugin.class.getName(), null, new ArtifactSummary("plugins3", "1.0.0"), ImmutableMap.of(), ImmutableSet.of("ping")));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount1Id, "interactive", "CallablePlugin"));
// test plugin with endpoint
Assert.assertEquals("hello", GSON.fromJson(callPluginMethod(plugins3Id, "interactive", "CallablePlugin", "ping", "user", ArtifactScope.USER, 200).getResponseBodyAsString(), String.class));
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, CallingPlugin.class.getPackage().getName());
ArtifactId plugins4Id = NamespaceId.DEFAULT.artifact("plugins4", "1.0.0");
// we also add test artifact as parent for calling plugin,
// when callable plugin is loaded by calling plugin's method,
// it will try with "testArtifact" parent - wouldn't be able to load
// then it will load using "wordcount" parent and succeed
Set<ArtifactRange> plugins4Parents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")), new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "testartifact", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(plugins4Id), CallingPlugin.class, manifest, plugins4Parents).getStatusLine().getStatusCode());
// test plugin with endpoint having endpoint-context parameter
Assert.assertEquals("hi user", GSON.fromJson(callPluginMethod(plugins4Id, "interactive", "CallingPlugin", "ping", "user", ArtifactScope.USER, 200).getResponseBodyAsString(), String.class));
// test plugin that accepts list of data and aggregates and returns result map
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, PluginWithPojo.class.getPackage().getName());
ArtifactId plugins5Id = NamespaceId.DEFAULT.artifact("aggregator", "1.0.0");
Set<ArtifactRange> plugins5Parents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(plugins5Id), PluginWithPojo.class, manifest, plugins5Parents).getStatusLine().getStatusCode());
// test plugin with endpoint having endpoint-context parameter
List<TestData> data = ImmutableList.of(new TestData(1, 10), new TestData(1, 20), new TestData(3, 15), new TestData(4, 5), new TestData(3, 15));
Map<Long, Long> expectedResult = new HashMap<>();
expectedResult.put(1L, 30L);
expectedResult.put(3L, 30L);
expectedResult.put(4L, 5L);
String response = callPluginMethod(plugins5Id, "interactive", "aggregator", "aggregate", GSON.toJson(data), ArtifactScope.USER, 200).getResponseBodyAsString();
Assert.assertEquals(expectedResult, GSON.fromJson(response, new TypeToken<Map<Long, Long>>() {
}.getType()));
// test calling a non-existent plugin method "bing"
callPluginMethod(plugins4Id, "interactive", "CallingPlugin", "bing", "user", ArtifactScope.USER, 404);
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, InvalidPlugin.class.getPackage().getName());
ArtifactId invalidPluginId = NamespaceId.DEFAULT.artifact("invalid", "1.0.0");
Set<ArtifactRange> invalidPluginParents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.code(), addPluginArtifact(Id.Artifact.fromEntityId(invalidPluginId), InvalidPlugin.class, manifest, invalidPluginParents).getStatusLine().getStatusCode());
// test adding plugin artifact which has endpoint method containing 3 params (invalid)
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, InvalidPluginMethodParams.class.getPackage().getName());
invalidPluginId = NamespaceId.DEFAULT.artifact("invalidParams", "1.0.0");
invalidPluginParents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.code(), addPluginArtifact(Id.Artifact.fromEntityId(invalidPluginId), InvalidPluginMethodParams.class, manifest, invalidPluginParents).getStatusLine().getStatusCode());
// test adding plugin artifact which has endpoint method containing 2 params
// but 2nd param is not EndpointPluginContext (invalid)
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, InvalidPluginMethodParamType.class.getPackage().getName());
invalidPluginId = NamespaceId.DEFAULT.artifact("invalidParamType", "1.0.0");
invalidPluginParents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.code(), addPluginArtifact(Id.Artifact.fromEntityId(invalidPluginId), InvalidPluginMethodParamType.class, manifest, invalidPluginParents).getStatusLine().getStatusCode());
// test adding plugin artifact which has endpoint methods containing 2 params
// but 2nd param is implementation and extensions of EndpointPluginContext, should succeed
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, PluginEndpointContextTestPlugin.class.getPackage().getName());
ArtifactId validPluginId = NamespaceId.DEFAULT.artifact("extender", "1.0.0");
Set<ArtifactRange> validPluginParents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(validPluginId), PluginEndpointContextTestPlugin.class, manifest, validPluginParents).getStatusLine().getStatusCode());
}
use of co.cask.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class ArtifactHttpHandlerTest method testGetPlugins.
@Test
public void testGetPlugins() throws Exception {
// add an app for plugins to extend
ArtifactId wordCount1Id = NamespaceId.DEFAULT.artifact("wordcount", "1.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordCount1Id), WordCountApp.class).getStatusLine().getStatusCode());
ArtifactId wordCount2Id = NamespaceId.DEFAULT.artifact("wordcount", "2.0.0");
Assert.assertEquals(HttpResponseStatus.OK.code(), addAppArtifact(Id.Artifact.fromEntityId(wordCount2Id), WordCountApp.class).getStatusLine().getStatusCode());
// add some plugins.
// plugins-1.0.0 extends wordcount[1.0.0,2.0.0)
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
ArtifactId pluginsId1 = NamespaceId.DEFAULT.artifact("plugins", "1.0.0");
Set<ArtifactRange> plugins1Parents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(pluginsId1), Plugin1.class, manifest, plugins1Parents).getStatusLine().getStatusCode());
// plugin-2.0.0 extends wordcount[1.0.0,3.0.0)
ArtifactId pluginsId2 = NamespaceId.DEFAULT.artifact("plugins", "2.0.0");
Set<ArtifactRange> plugins2Parents = Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "wordcount", new ArtifactVersion("1.0.0"), new ArtifactVersion("3.0.0")));
Assert.assertEquals(HttpResponseStatus.OK.code(), addPluginArtifact(Id.Artifact.fromEntityId(pluginsId2), Plugin1.class, manifest, plugins2Parents).getStatusLine().getStatusCode());
ArtifactSummary plugins1Artifact = new ArtifactSummary("plugins", "1.0.0");
ArtifactSummary plugins2Artifact = new ArtifactSummary("plugins", "2.0.0");
// get plugin types, should be the same for both
Set<String> expectedTypes = Sets.newHashSet("dummy", "callable");
Set<String> actualTypes = getPluginTypes(wordCount1Id);
Assert.assertEquals(expectedTypes, actualTypes);
actualTypes = getPluginTypes(wordCount2Id);
Assert.assertEquals(expectedTypes, actualTypes);
// get plugin summaries. wordcount1 should see plugins from both plugin artifacts
Set<PluginSummary> expectedSummaries = Sets.newHashSet(new PluginSummary("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), plugins1Artifact), new PluginSummary("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), plugins2Artifact));
Set<PluginSummary> actualSummaries = getPluginSummaries(wordCount1Id, "dummy");
Assert.assertEquals(expectedSummaries, actualSummaries);
expectedSummaries = Sets.newHashSet(new PluginSummary("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins1Artifact), new PluginSummary("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins2Artifact));
actualSummaries = getPluginSummaries(wordCount1Id, "callable");
Assert.assertEquals(expectedSummaries, actualSummaries);
// wordcount2 should only see plugins from plugins2 artifact
expectedSummaries = Sets.newHashSet(new PluginSummary("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), plugins2Artifact));
actualSummaries = getPluginSummaries(wordCount2Id, "dummy");
Assert.assertEquals(expectedSummaries, actualSummaries);
expectedSummaries = Sets.newHashSet(new PluginSummary("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins2Artifact));
actualSummaries = getPluginSummaries(wordCount2Id, "callable");
Assert.assertEquals(expectedSummaries, actualSummaries);
// get plugin info. Again, wordcount1 should see plugins from both artifacts
Map<String, PluginPropertyField> p1Properties = ImmutableMap.of("x", new PluginPropertyField("x", "", "int", true, false), "stuff", new PluginPropertyField("stuff", "", "string", true, true));
Map<String, PluginPropertyField> p2Properties = ImmutableMap.of("v", new PluginPropertyField("v", "value to return when called", "int", true, false));
Set<PluginInfo> expectedInfos = Sets.newHashSet(new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), "config", plugins1Artifact, p1Properties, new HashSet<>()), new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), "config", plugins2Artifact, p1Properties, new HashSet<>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount1Id, "dummy", "Plugin1"));
expectedInfos = Sets.newHashSet(new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), "config", plugins1Artifact, p2Properties, new HashSet<>()), new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), "config", plugins2Artifact, p2Properties, new HashSet<>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount1Id, "callable", "Plugin2"));
// while wordcount2 should only see plugins from plugins2 artifact
expectedInfos = Sets.newHashSet(new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), "config", plugins2Artifact, p1Properties, new HashSet<>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount2Id, "dummy", "Plugin1"));
expectedInfos = Sets.newHashSet(new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), "config", plugins2Artifact, p2Properties, new HashSet<>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount2Id, "callable", "Plugin2"));
}
use of co.cask.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class PluginFinderTestBase method testFindPlugin.
@Test
public void testFindPlugin() throws Exception {
// Deploy some artifacts
File appArtifact = createAppJar(PluginTestApp.class);
File pluginArtifact = createPluginJar(Plugin1.class);
ArtifactId appArtifactId = NamespaceId.DEFAULT.artifact("app", "1.0");
artifactRepo.addArtifact(Id.Artifact.fromEntityId(appArtifactId), appArtifact);
ArtifactId pluginArtifactId = NamespaceId.DEFAULT.artifact("plugin", "1.0");
artifactRepo.addArtifact(Id.Artifact.fromEntityId(pluginArtifactId), pluginArtifact, Collections.singleton(new ArtifactRange(appArtifactId.getNamespace(), appArtifactId.getArtifact(), new ArtifactVersion(appArtifactId.getVersion()), true, new ArtifactVersion(appArtifactId.getVersion()), true)), null);
// Find the plugin
PluginFinder finder = getPluginFinder();
Map.Entry<ArtifactDescriptor, PluginClass> entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector());
Assert.assertNotNull(entry);
Assert.assertEquals(pluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
Assert.assertEquals("Plugin1", entry.getValue().getName());
Assert.assertEquals("dummy", entry.getValue().getType());
// Looking for a non-existing should throw
try {
finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy2", "pluginx", new PluginSelector());
Assert.fail("A PluginNotExistsException is expected");
} catch (PluginNotExistsException e) {
// expected
}
// Deploy the same plugin artifact to the system namespace, without any parent
ArtifactId systemPluginArtifactId = NamespaceId.SYSTEM.artifact("pluginsystem", "1.0");
artifactRepo.addArtifact(Id.Artifact.fromEntityId(systemPluginArtifactId), pluginArtifact);
entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector());
// The selector always select the last one, hence the USER once will be selected
Assert.assertNotNull(entry);
Assert.assertEquals(pluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
Assert.assertEquals("Plugin1", entry.getValue().getName());
Assert.assertEquals("dummy", entry.getValue().getType());
// Use a different selector that returns the first entry, hence expect the SYSTEM one being returned
entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector() {
@Override
public Map.Entry<co.cask.cdap.api.artifact.ArtifactId, PluginClass> select(SortedMap<co.cask.cdap.api.artifact.ArtifactId, PluginClass> plugins) {
return plugins.entrySet().iterator().next();
}
});
Assert.assertNotNull(entry);
Assert.assertEquals(systemPluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
Assert.assertEquals("Plugin1", entry.getValue().getName());
Assert.assertEquals("dummy", entry.getValue().getType());
}
use of co.cask.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class RemotePluginFinder method findPlugin.
@Override
public Map.Entry<ArtifactDescriptor, PluginClass> findPlugin(NamespaceId pluginNamespaceId, ArtifactId parentArtifactId, String pluginType, String pluginName, PluginSelector selector) throws PluginNotExistsException {
try {
return Retries.callWithRetries(() -> {
List<PluginInfo> infos = getPlugins(pluginNamespaceId, parentArtifactId, pluginType, pluginName);
if (infos.isEmpty()) {
throw new PluginNotExistsException(pluginNamespaceId, pluginType, pluginName);
}
SortedMap<co.cask.cdap.api.artifact.ArtifactId, PluginClass> plugins = new TreeMap<>();
for (PluginInfo info : infos) {
ArtifactSummary artifactSummary = info.getArtifact();
co.cask.cdap.api.artifact.ArtifactId pluginArtifactId = new co.cask.cdap.api.artifact.ArtifactId(artifactSummary.getName(), new ArtifactVersion(artifactSummary.getVersion()), artifactSummary.getScope());
PluginClass pluginClass = new PluginClass(info.getType(), info.getName(), info.getDescription(), info.getClassName(), info.getConfigFieldName(), info.getProperties(), info.getEndpoints());
plugins.put(pluginArtifactId, pluginClass);
}
Map.Entry<co.cask.cdap.api.artifact.ArtifactId, PluginClass> selected = selector.select(plugins);
if (selected == null) {
throw new PluginNotExistsException(pluginNamespaceId, pluginType, pluginName);
}
Location artifactLocation = getArtifactLocation(Artifacts.toArtifactId(pluginNamespaceId, selected.getKey()));
return Maps.immutableEntry(new ArtifactDescriptor(selected.getKey(), artifactLocation), selected.getValue());
}, retryStrategy);
} catch (PluginNotExistsException e) {
throw e;
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
Aggregations