Search in sources :

Example 11 with ArtifactRange

use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.

the class ArtifactHttpHandler method parseExtendsHeader.

// find out if this artifact extends other artifacts. If so, there will be a header like
// 'Artifact-Extends: <name>[<lowerversion>,<upperversion>]/<name>[<lowerversion>,<upperversion>]:
// for example: 'Artifact-Extends: etl-batch[1.0.0,2.0.0]/etl-realtime[1.0.0:3.0.0]
private Set<ArtifactRange> parseExtendsHeader(NamespaceId namespace, String extendsHeader) throws BadRequestException {
    Set<ArtifactRange> parentArtifacts = Sets.newHashSet();
    if (extendsHeader != null) {
        for (String parent : Splitter.on('/').split(extendsHeader)) {
            parent = parent.trim();
            ArtifactRange range;
            // try parsing it as a namespaced range like system:etl-batch[1.0.0,2.0.0)
            try {
                range = ArtifactRanges.parseArtifactRange(parent);
                // only support extending an artifact that is in the same namespace, or system namespace
                if (!NamespaceId.SYSTEM.getNamespace().equals(range.getNamespace()) && !namespace.getNamespace().equals(range.getNamespace())) {
                    throw new BadRequestException(String.format("Parent artifact %s must be in the same namespace or a system artifact.", parent));
                }
            } catch (InvalidArtifactRangeException e) {
                // if this failed, try parsing as a non-namespaced range like etl-batch[1.0.0,2.0.0)
                try {
                    range = ArtifactRanges.parseArtifactRange(namespace.getNamespace(), parent);
                } catch (InvalidArtifactRangeException e1) {
                    throw new BadRequestException(String.format("Invalid artifact range %s: %s", parent, e1.getMessage()));
                }
            }
            parentArtifacts.add(range);
        }
    }
    return parentArtifacts;
}
Also used : ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) InvalidArtifactRangeException(co.cask.cdap.api.artifact.InvalidArtifactRangeException) BadRequestException(co.cask.cdap.common.BadRequestException)

Example 12 with ArtifactRange

use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.

the class ArtifactRangeTest method testWhitespace.

@Test
public void testWhitespace() throws InvalidArtifactRangeException {
    ArtifactRange range = ArtifactRanges.parseArtifactRange(NamespaceId.DEFAULT.getNamespace(), "name[ 1.0.0 , 2.0.0 )");
    Assert.assertEquals(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "name", new ArtifactVersion("1.0.0"), true, new ArtifactVersion("2.0.0"), false), range);
}
Also used : ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) Test(org.junit.Test)

Example 13 with ArtifactRange

use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.

the class ArtifactRepositoryTest method testMultipleParentVersions.

@Test(expected = InvalidArtifactException.class)
public void testMultipleParentVersions() throws InvalidArtifactException {
    Id.Artifact child = Id.Artifact.from(Id.Namespace.SYSTEM, "abc", "1.0.0");
    ArtifactRepository.validateParentSet(child, ImmutableSet.of(new ArtifactRange(NamespaceId.SYSTEM.getNamespace(), "r1", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")), new ArtifactRange(NamespaceId.SYSTEM.getNamespace(), "r1", new ArtifactVersion("3.0.0"), new ArtifactVersion("4.0.0"))));
}
Also used : ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) ArtifactId(co.cask.cdap.api.artifact.ArtifactId) Id(co.cask.cdap.proto.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) Test(org.junit.Test)

Example 14 with ArtifactRange

use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.

the class ArtifactHttpHandlerTest method testPluginNamespaceIsolation.

@Test
public void testPluginNamespaceIsolation() throws Exception {
    // add a system artifact. currently can't do this through the rest api (by design)
    // so bypass it and use the repository directly
    Id.Artifact systemId = Id.Artifact.from(Id.Namespace.SYSTEM, "wordcount", "1.0.0");
    File systemArtifact = buildAppArtifact(WordCountApp.class, "wordcount-1.0.0.jar");
    artifactRepository.addArtifact(systemId, systemArtifact, Sets.<ArtifactRange>newHashSet());
    Set<ArtifactRange> parents = Sets.newHashSet(new ArtifactRange(systemId.getNamespace().getId(), systemId.getName(), systemId.getVersion(), true, systemId.getVersion(), true));
    Id.Namespace namespace1 = Id.Namespace.from("ns1");
    Id.Namespace namespace2 = Id.Namespace.from("ns2");
    createNamespace(namespace1.getId());
    createNamespace(namespace2.getId());
    try {
        // add some plugins in namespace1. Will contain Plugin1 and Plugin2
        Manifest manifest = new Manifest();
        manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
        Id.Artifact pluginsId1 = Id.Artifact.from(namespace1, "plugins1", "1.0.0");
        Assert.assertEquals(HttpResponseStatus.OK.getCode(), addPluginArtifact(pluginsId1, Plugin1.class, manifest, parents).getStatusLine().getStatusCode());
        // add some plugins in namespace2. Will contain Plugin1 and Plugin2
        manifest = new Manifest();
        manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
        Id.Artifact pluginsId2 = Id.Artifact.from(namespace2, "plugins2", "1.0.0");
        Assert.assertEquals(HttpResponseStatus.OK.getCode(), addPluginArtifact(pluginsId2, Plugin1.class, manifest, parents).getStatusLine().getStatusCode());
        ArtifactSummary artifact1 = new ArtifactSummary(pluginsId1.getName(), pluginsId1.getVersion().getVersion(), ArtifactScope.USER);
        ArtifactSummary artifact2 = new ArtifactSummary(pluginsId2.getName(), pluginsId2.getVersion().getVersion(), ArtifactScope.USER);
        PluginSummary summary1Namespace1 = new PluginSummary("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), artifact1);
        PluginSummary summary2Namespace1 = new PluginSummary("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), artifact1);
        PluginSummary summary1Namespace2 = new PluginSummary("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), artifact2);
        PluginSummary summary2Namespace2 = new PluginSummary("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), artifact2);
        PluginInfo info1Namespace1 = new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), artifact1, ImmutableMap.of("x", new PluginPropertyField("x", "", "int", true, false), "stuff", new PluginPropertyField("stuff", "", "string", true, true)), new HashSet<String>());
        PluginInfo info2Namespace1 = new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), artifact1, ImmutableMap.of("v", new PluginPropertyField("v", "value to return when called", "int", true, false)), new HashSet<String>());
        PluginInfo info1Namespace2 = new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), artifact2, ImmutableMap.of("x", new PluginPropertyField("x", "", "int", true, false), "stuff", new PluginPropertyField("stuff", "", "string", true, true)), new HashSet<String>());
        PluginInfo info2Namespace2 = new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), artifact2, ImmutableMap.of("v", new PluginPropertyField("v", "value to return when called", "int", true, false)), new HashSet<String>());
        Id.Artifact namespace1Artifact = Id.Artifact.from(namespace1, systemId.getName(), systemId.getVersion());
        Id.Artifact namespace2Artifact = Id.Artifact.from(namespace2, systemId.getName(), systemId.getVersion());
        // should see same types in both namespaces
        Assert.assertEquals(ImmutableSet.of("dummy", "callable"), getPluginTypes(namespace1Artifact, ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of("dummy", "callable"), getPluginTypes(namespace2Artifact, ArtifactScope.SYSTEM));
        // should see that plugins in namespace1 come only from the namespace1 artifact
        Assert.assertEquals(ImmutableSet.of(summary1Namespace1), getPluginSummaries(namespace1Artifact, "dummy", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(summary2Namespace1), getPluginSummaries(namespace1Artifact, "callable", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(info1Namespace1), getPluginInfos(namespace1Artifact, "dummy", "Plugin1", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(info2Namespace1), getPluginInfos(namespace1Artifact, "callable", "Plugin2", ArtifactScope.SYSTEM));
        // should see that plugins in namespace2 come only from the namespace2 artifact
        Assert.assertEquals(ImmutableSet.of(summary1Namespace2), getPluginSummaries(namespace2Artifact, "dummy", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(summary2Namespace2), getPluginSummaries(namespace2Artifact, "callable", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(info1Namespace2), getPluginInfos(namespace2Artifact, "dummy", "Plugin1", ArtifactScope.SYSTEM));
        Assert.assertEquals(ImmutableSet.of(info2Namespace2), getPluginInfos(namespace2Artifact, "callable", "Plugin2", ArtifactScope.SYSTEM));
    } finally {
        deleteNamespace("iso1");
        deleteNamespace("iso2");
    }
}
Also used : Plugin2(co.cask.cdap.internal.app.runtime.artifact.plugin.Plugin2) Plugin1(co.cask.cdap.internal.app.runtime.artifact.plugin.Plugin1) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) Manifest(java.util.jar.Manifest) PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) ArtifactSummary(co.cask.cdap.api.artifact.ArtifactSummary) PluginInfo(co.cask.cdap.proto.artifact.PluginInfo) Id(co.cask.cdap.proto.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) PluginSummary(co.cask.cdap.proto.artifact.PluginSummary) File(java.io.File) Test(org.junit.Test)

Example 15 with ArtifactRange

use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.

the class ArtifactHttpHandlerTest method testPluginWithEndpoints.

@Test
public void testPluginWithEndpoints() throws Exception {
    // add an app for plugins to extend
    Id.Artifact wordCount1Id = Id.Artifact.from(Id.Namespace.DEFAULT, "wordcount", "1.0.0");
    Assert.assertEquals(HttpResponseStatus.OK.getCode(), addAppArtifact(wordCount1Id, WordCountApp.class).getStatusLine().getStatusCode());
    Id.Artifact wordCount2Id = Id.Artifact.from(Id.Namespace.DEFAULT, "testartifact", "1.0.0");
    Assert.assertEquals(HttpResponseStatus.OK.getCode(), addAppArtifact(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());
    Id.Artifact plugins3Id = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(plugins3Id, CallablePlugin.class, manifest, plugins3Parents).getStatusLine().getStatusCode());
    Set<PluginInfo> expectedInfos = Sets.newHashSet(new PluginInfo("CallablePlugin", "interactive", "This is plugin with endpoint", CallablePlugin.class.getName(), new ArtifactSummary("plugins3", "1.0.0"), ImmutableMap.<String, PluginPropertyField>of(), ImmutableSet.<String>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());
    Id.Artifact plugins4Id = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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());
    Id.Artifact plugins5Id = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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());
    Id.Artifact invalidPluginId = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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 = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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 = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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());
    Id.Artifact validPluginId = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(validPluginId, PluginEndpointContextTestPlugin.class, manifest, validPluginParents).getStatusLine().getStatusCode());
}
Also used : TestData(co.cask.cdap.internal.app.runtime.artifact.plugin.p5.TestData) CallingPlugin(co.cask.cdap.internal.app.runtime.artifact.plugin.p4.CallingPlugin) HashMap(java.util.HashMap) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) PluginWithPojo(co.cask.cdap.internal.app.runtime.artifact.plugin.p5.PluginWithPojo) InvalidPluginMethodParamType(co.cask.cdap.internal.app.runtime.artifact.plugin.invalid3.InvalidPluginMethodParamType) PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) CallablePlugin(co.cask.cdap.internal.app.runtime.artifact.plugin.p3.CallablePlugin) ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) InvalidPluginMethodParams(co.cask.cdap.internal.app.runtime.artifact.plugin.invalid2.InvalidPluginMethodParams) PluginInfo(co.cask.cdap.proto.artifact.PluginInfo) Manifest(java.util.jar.Manifest) InvalidPlugin(co.cask.cdap.internal.app.runtime.artifact.plugin.invalid.InvalidPlugin) PluginEndpointContextTestPlugin(co.cask.cdap.internal.app.runtime.artifact.plugin.endpointtest.PluginEndpointContextTestPlugin) ArtifactSummary(co.cask.cdap.api.artifact.ArtifactSummary) WordCountApp(co.cask.cdap.WordCountApp) Id(co.cask.cdap.proto.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) Test(org.junit.Test)

Aggregations

ArtifactRange (co.cask.cdap.api.artifact.ArtifactRange)46 ArtifactVersion (co.cask.cdap.api.artifact.ArtifactVersion)33 Test (org.junit.Test)31 NamespaceId (co.cask.cdap.proto.id.NamespaceId)28 Id (co.cask.cdap.proto.Id)24 PluginClass (co.cask.cdap.api.plugin.PluginClass)17 PluginPropertyField (co.cask.cdap.api.plugin.PluginPropertyField)13 ArtifactId (co.cask.cdap.proto.id.ArtifactId)13 File (java.io.File)11 Manifest (java.util.jar.Manifest)11 HashSet (java.util.HashSet)9 ArtifactNotFoundException (co.cask.cdap.common.ArtifactNotFoundException)8 ArtifactId (co.cask.cdap.api.artifact.ArtifactId)7 ImmutableSet (com.google.common.collect.ImmutableSet)7 Set (java.util.Set)7 ArtifactSummary (co.cask.cdap.api.artifact.ArtifactSummary)6 ApplicationClass (co.cask.cdap.api.artifact.ApplicationClass)5 PluginNotExistsException (co.cask.cdap.internal.app.runtime.plugin.PluginNotExistsException)5 ArtifactInfo (co.cask.cdap.api.artifact.ArtifactInfo)4 IOException (java.io.IOException)4