Search in sources :

Example 41 with ArtifactRange

use of io.cdap.cdap.api.artifact.ArtifactRange in project cdap by cdapio.

the class ArtifactHttpHandler method getArtifactVersions.

@GET
@Path("/namespaces/{namespace-id}/artifacts/{artifact-name}")
public void getArtifactVersions(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("artifact-name") String artifactName, @QueryParam("scope") @DefaultValue("user") String scope, @QueryParam("artifactVersion") String versionRange, @QueryParam("limit") @DefaultValue("2147483647") String limit, @QueryParam("order") @DefaultValue("UNORDERED") String order) throws Exception {
    NamespaceId namespace = validateAndGetScopedNamespace(Ids.namespace(namespaceId), scope);
    ArtifactRange range = versionRange == null ? null : new ArtifactRange(namespaceId, artifactName, ArtifactVersionRange.parse(versionRange));
    int limitNumber = Integer.parseInt(limit);
    limitNumber = limitNumber <= 0 ? Integer.MAX_VALUE : limitNumber;
    ArtifactSortOrder sortOrder = ArtifactSortOrder.valueOf(order);
    try {
        if (range == null) {
            responder.sendJson(HttpResponseStatus.OK, GSON.toJson(artifactRepository.getArtifactSummaries(namespace, artifactName, limitNumber, sortOrder)));
        } else {
            responder.sendJson(HttpResponseStatus.OK, GSON.toJson(artifactRepository.getArtifactSummaries(range, limitNumber, sortOrder)));
        }
    } catch (IOException e) {
        LOG.error("Exception reading artifacts named {} for namespace {} from the store.", artifactName, namespaceId, e);
        responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error reading artifact metadata from the store.");
    }
}
Also used : ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) IOException(java.io.IOException) ArtifactSortOrder(io.cdap.cdap.proto.artifact.ArtifactSortOrder) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET)

Example 42 with ArtifactRange

use of io.cdap.cdap.api.artifact.ArtifactRange in project cdap by cdapio.

the class ArtifactStore method deleteMeta.

private void deleteMeta(StructuredTableContext context, Id.Artifact artifactId, ArtifactData oldMeta) throws IOException {
    // delete old artifact data
    StructuredTable artifactTable = getTable(context, StoreDefinition.ArtifactStore.ARTIFACT_DATA_TABLE);
    ArtifactCell artifactCell = new ArtifactCell(artifactId);
    artifactTable.delete(artifactCell.keys);
    // delete old appclass metadata
    StructuredTable appClassTable = getTable(context, StoreDefinition.ArtifactStore.APP_DATA_TABLE);
    for (ApplicationClass appClass : oldMeta.meta.getClasses().getApps()) {
        AppClassKey appClassKey = new AppClassKey(artifactId.getNamespace().toEntityId(), appClass.getClassName());
        deleteRangeFromTable(appClassTable, Range.singleton(appClassKey.keys));
    }
    // delete old plugins, we loop twice to only access to one table at a time to prevent deadlock
    StructuredTable pluginDataTable = getTable(context, StoreDefinition.ArtifactStore.PLUGIN_DATA_TABLE);
    for (PluginClass pluginClass : oldMeta.meta.getClasses().getPlugins()) {
        // delete metadata for each artifact this plugin extends
        for (ArtifactRange artifactRange : oldMeta.meta.getUsableBy()) {
            // these four fields are prefixes of the plugin table primary keys
            PluginKeyPrefix pluginKey = new PluginKeyPrefix(artifactRange.getNamespace(), artifactRange.getName(), pluginClass.getType(), pluginClass.getName());
            pluginDataTable.delete(concatFields(pluginKey.keys, artifactCell.keys));
        }
    }
    // Delete the universal plugin row
    StructuredTable uniPluginTable = getTable(context, StoreDefinition.ArtifactStore.UNIV_PLUGIN_DATA_TABLE);
    for (PluginClass pluginClass : oldMeta.meta.getClasses().getPlugins()) {
        if (oldMeta.meta.getUsableBy().isEmpty()) {
            UniversalPluginKeyPrefix pluginKey = new UniversalPluginKeyPrefix(artifactId.getNamespace().getId(), pluginClass.getType(), pluginClass.getName());
            uniPluginTable.delete(concatFields(pluginKey.keys, artifactCell.keys));
        }
    }
    // delete the old jar file
    try {
        new EntityImpersonator(artifactId.toEntityId(), impersonator).impersonate(() -> {
            Locations.getLocationFromAbsolutePath(locationFactory, oldMeta.getLocationPath()).delete();
            return null;
        });
    } catch (IOException ioe) {
        throw ioe;
    } catch (Exception e) {
        // this should not happen
        throw Throwables.propagate(e);
    }
}
Also used : StructuredTable(io.cdap.cdap.spi.data.StructuredTable) EntityImpersonator(io.cdap.cdap.security.impersonation.EntityImpersonator) ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) IOException(java.io.IOException) PluginClass(io.cdap.cdap.api.plugin.PluginClass) ArtifactAlreadyExistsException(io.cdap.cdap.common.ArtifactAlreadyExistsException) TransactionException(io.cdap.cdap.spi.data.transaction.TransactionException) PluginNotExistsException(io.cdap.cdap.internal.app.runtime.plugin.PluginNotExistsException) IOException(java.io.IOException) TableNotFoundException(io.cdap.cdap.spi.data.TableNotFoundException) ArtifactNotFoundException(io.cdap.cdap.common.ArtifactNotFoundException)

Example 43 with ArtifactRange

use of io.cdap.cdap.api.artifact.ArtifactRange in project cdap by cdapio.

the class ArtifactRepositoryTest method testCyclicDependenciesAreInvalid.

@Test
public void testCyclicDependenciesAreInvalid() throws Exception {
    // create a1 artifact that extends app and a2
    io.cdap.cdap.proto.id.ArtifactId a1Id = NamespaceId.DEFAULT.artifact("a1", "1.0.0");
    io.cdap.cdap.proto.id.ArtifactId a2Id = NamespaceId.DEFAULT.artifact("a2", "1.0.0");
    Manifest manifest = createManifest(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
    File jarFile = createPluginJar(Plugin1.class, new File(tmpDir, "a1-1.0.0.jar"), manifest);
    Set<ArtifactRange> parents = ImmutableSet.of(new ArtifactRange(APP_ARTIFACT_ID.getNamespace().getId(), APP_ARTIFACT_ID.getName(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")), new ArtifactRange(a2Id.getNamespace(), a2Id.getArtifact(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
    artifactRepository.addArtifact(Id.Artifact.fromEntityId(a1Id), jarFile, parents, null);
    // create a2 artifact that extends a1, which should be invalid
    manifest = createManifest(ManifestFields.EXPORT_PACKAGE, Plugin2.class.getPackage().getName());
    jarFile = createPluginJar(Plugin2.class, new File(tmpDir, "a2-1.0.0.jar"), manifest);
    parents = ImmutableSet.of(new ArtifactRange(a1Id.getNamespace(), a1Id.getArtifact(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
    try {
        artifactRepository.addArtifact(Id.Artifact.fromEntityId(a2Id), jarFile, parents, null);
        Assert.fail("Artifact repository did not catch a cyclic dependency.");
    } catch (InvalidArtifactException e) {
    // expected
    }
}
Also used : Plugin2(io.cdap.cdap.internal.app.runtime.artifact.plugin.Plugin2) TestPlugin2(io.cdap.cdap.internal.app.plugins.test.TestPlugin2) ArtifactVersion(io.cdap.cdap.api.artifact.ArtifactVersion) ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) Manifest(java.util.jar.Manifest) File(java.io.File) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException) Test(org.junit.Test)

Example 44 with ArtifactRange

use of io.cdap.cdap.api.artifact.ArtifactRange in project cdap by cdapio.

the class ArtifactRepositoryTest method testPluginSelector.

@Test
public void testPluginSelector() throws Exception {
    // No plugin yet
    ArtifactRange appArtifactRange = new ArtifactRange(APP_ARTIFACT_ID.getNamespace().getId(), APP_ARTIFACT_ID.getName(), APP_ARTIFACT_ID.getVersion(), true, APP_ARTIFACT_ID.getVersion(), true);
    try {
        artifactRepository.findPlugin(NamespaceId.DEFAULT, appArtifactRange, "plugin", "TestPlugin2", new PluginSelector());
        Assert.fail();
    } catch (PluginNotExistsException e) {
    // expected
    }
    File pluginDir = DirUtils.createTempDir(tmpDir);
    // Create a plugin jar. It contains two plugins, TestPlugin and TestPlugin2 inside.
    Id.Artifact artifact1Id = Id.Artifact.from(Id.Namespace.DEFAULT, "myPlugin", "1.0");
    Manifest manifest = createManifest(ManifestFields.EXPORT_PACKAGE, TestPlugin.class.getPackage().getName());
    File jarFile = createPluginJar(TestPlugin.class, new File(tmpDir, "myPlugin-1.0.jar"), manifest);
    // Build up the plugin repository.
    Set<ArtifactRange> parents = ImmutableSet.of(new ArtifactRange(APP_ARTIFACT_ID.getNamespace().getId(), APP_ARTIFACT_ID.getName(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
    artifactRepository.addArtifact(artifact1Id, jarFile, parents, null);
    // Should get the only version.
    Map.Entry<ArtifactDescriptor, PluginClass> plugin = artifactRepository.findPlugin(NamespaceId.DEFAULT, appArtifactRange, "plugin", "TestPlugin2", new PluginSelector());
    Assert.assertNotNull(plugin);
    Assert.assertEquals(new ArtifactVersion("1.0"), plugin.getKey().getArtifactId().getVersion());
    Assert.assertEquals("TestPlugin2", plugin.getValue().getName());
    Locations.linkOrCopyOverwrite(plugin.getKey().getLocation(), new File(pluginDir, Artifacts.getFileName(plugin.getKey().getArtifactId())));
    // Create another plugin jar with later version and update the repository
    Id.Artifact artifact2Id = Id.Artifact.from(Id.Namespace.DEFAULT, "myPlugin", "2.0");
    jarFile = createPluginJar(TestPlugin.class, new File(tmpDir, "myPlugin-2.0.jar"), manifest);
    artifactRepository.addArtifact(artifact2Id, jarFile, parents, null);
    // Should select the latest version
    plugin = artifactRepository.findPlugin(NamespaceId.DEFAULT, appArtifactRange, "plugin", "TestPlugin2", new PluginSelector());
    Assert.assertNotNull(plugin);
    Assert.assertEquals(new ArtifactVersion("2.0"), plugin.getKey().getArtifactId().getVersion());
    Assert.assertEquals("TestPlugin2", plugin.getValue().getName());
    Locations.linkOrCopyOverwrite(plugin.getKey().getLocation(), new File(pluginDir, Artifacts.getFileName(plugin.getKey().getArtifactId())));
    // Load the Plugin class from the classLoader.
    try (PluginInstantiator instantiator = new PluginInstantiator(cConf, appClassLoader, pluginDir)) {
        ClassLoader pluginClassLoader = instantiator.getArtifactClassLoader(plugin.getKey().getArtifactId());
        Class<?> pluginClass = pluginClassLoader.loadClass(TestPlugin2.class.getName());
        // Use a custom plugin selector to select with smallest version
        plugin = artifactRepository.findPlugin(NamespaceId.DEFAULT, appArtifactRange, "plugin", "TestPlugin2", new PluginSelector() {

            @Override
            public Map.Entry<ArtifactId, PluginClass> select(SortedMap<ArtifactId, PluginClass> plugins) {
                return plugins.entrySet().iterator().next();
            }
        });
        Assert.assertNotNull(plugin);
        Assert.assertEquals(new ArtifactVersion("1.0"), plugin.getKey().getArtifactId().getVersion());
        Assert.assertEquals("TestPlugin2", plugin.getValue().getName());
        // Load the Plugin class again from the current plugin selected
        // The plugin class should be different (from different ClassLoader)
        // The empty class should be the same (from the plugin lib ClassLoader)
        pluginClassLoader = instantiator.getArtifactClassLoader(plugin.getKey().getArtifactId());
        Assert.assertNotSame(pluginClass, pluginClassLoader.loadClass(TestPlugin2.class.getName()));
        // From the pluginClassLoader, loading export classes from the template jar should be allowed
        Class<?> cls = pluginClassLoader.loadClass(PluginTestRunnable.class.getName());
        // The class should be loaded from the parent artifact's classloader
        Assert.assertSame(appClassLoader.loadClass(PluginTestRunnable.class.getName()), cls);
        // From the plugin classloader, all cdap api classes is loadable as well.
        cls = pluginClassLoader.loadClass(Application.class.getName());
        // The Application class should be the same as the one in the system classloader
        Assert.assertSame(Application.class, cls);
    }
}
Also used : PluginSelector(io.cdap.cdap.api.plugin.PluginSelector) TestPlugin2(io.cdap.cdap.internal.app.plugins.test.TestPlugin2) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) PluginTestRunnable(io.cdap.cdap.internal.app.runtime.artifact.app.plugin.PluginTestRunnable) ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) Manifest(java.util.jar.Manifest) PluginNotExistsException(io.cdap.cdap.internal.app.runtime.plugin.PluginNotExistsException) ArtifactVersion(io.cdap.cdap.api.artifact.ArtifactVersion) SortedMap(java.util.SortedMap) ProgramClassLoader(io.cdap.cdap.internal.app.runtime.ProgramClassLoader) FilterClassLoader(io.cdap.cdap.common.lang.FilterClassLoader) TestPlugin(io.cdap.cdap.internal.app.plugins.test.TestPlugin) PluginInstantiator(io.cdap.cdap.internal.app.runtime.plugin.PluginInstantiator) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) PluginId(io.cdap.cdap.proto.id.PluginId) Id(io.cdap.cdap.common.id.Id) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) PluginClass(io.cdap.cdap.api.plugin.PluginClass) File(java.io.File) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) Test(org.junit.Test)

Example 45 with ArtifactRange

use of io.cdap.cdap.api.artifact.ArtifactRange in project cdap by cdapio.

the class ArtifactStoreTest method testPluginNamespaceIsolation.

@Test
public void testPluginNamespaceIsolation() throws Exception {
    // write some system artifact
    Id.Artifact systemAppArtifact = Id.Artifact.from(Id.Namespace.SYSTEM, "app", "1.0.0");
    ArtifactMeta systemAppMeta = new ArtifactMeta(ArtifactClasses.builder().addApp(new ApplicationClass("io.cdap.class", "desc", null)).build());
    writeArtifact(systemAppArtifact, systemAppMeta, "app contents");
    Set<ArtifactRange> usableBy = ImmutableSet.of(new ArtifactRange(systemAppArtifact.getNamespace().getId(), systemAppArtifact.getName(), systemAppArtifact.getVersion(), true, systemAppArtifact.getVersion(), true));
    PluginClass plugin = PluginClass.builder().setName("plugin1").setType("atype").setDescription("").setClassName("c.c.c.plugin1").setConfigFieldName("cfg").setProperties(ImmutableMap.of()).build();
    // write a plugins artifact in namespace1
    NamespaceId namespace1 = Ids.namespace("ns1");
    Id.Artifact artifact1 = Id.Artifact.from((Id.Namespace.fromEntityId(namespace1)), "plugins1", "1.0.0");
    ArtifactMeta meta1 = new ArtifactMeta(ArtifactClasses.builder().addPlugin(plugin).build(), usableBy);
    String contents1 = "plugin1 contents";
    writeArtifact(artifact1, meta1, contents1);
    // write a plugins artifact in namespace2
    NamespaceId namespace2 = Ids.namespace("ns2");
    Id.Artifact artifact2 = Id.Artifact.from(Id.Namespace.fromEntityId(namespace2), "plugins2", "1.0.0");
    ArtifactMeta meta2 = new ArtifactMeta(ArtifactClasses.builder().addPlugin(plugin).build(), usableBy);
    String contents2 = "plugin2 contents";
    writeArtifact(artifact2, meta2, contents2);
    try {
        // this should only get plugins from artifact1
        SortedMap<ArtifactDescriptor, Set<PluginClass>> plugins = artifactStore.getPluginClasses(namespace1, systemAppArtifact);
        Assert.assertEquals(1, plugins.size());
        ArtifactDescriptor artifactDescriptor = plugins.firstKey();
        Assert.assertEquals(artifact1.toArtifactId(), artifactDescriptor.getArtifactId());
        assertContentsEqual(contents1, artifactDescriptor.getLocation());
        // this should only get plugins from artifact2
        plugins = artifactStore.getPluginClasses(namespace2, systemAppArtifact);
        Assert.assertEquals(1, plugins.size());
        artifactDescriptor = plugins.firstKey();
        Assert.assertEquals(artifact2.toArtifactId(), artifactDescriptor.getArtifactId());
        assertContentsEqual(contents2, artifactDescriptor.getLocation());
    } finally {
        artifactStore.clear(namespace1);
        artifactStore.clear(namespace2);
        artifactStore.clear(NamespaceId.SYSTEM);
    }
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ArtifactRange(io.cdap.cdap.api.artifact.ArtifactRange) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) Id(io.cdap.cdap.common.id.Id) ArtifactId(io.cdap.cdap.proto.id.ArtifactId) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) PluginClass(io.cdap.cdap.api.plugin.PluginClass) Test(org.junit.Test)

Aggregations

ArtifactRange (io.cdap.cdap.api.artifact.ArtifactRange)107 ArtifactVersion (io.cdap.cdap.api.artifact.ArtifactVersion)77 Test (org.junit.Test)68 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)54 PluginClass (io.cdap.cdap.api.plugin.PluginClass)42 Id (io.cdap.cdap.common.id.Id)40 ArtifactId (io.cdap.cdap.proto.id.ArtifactId)36 File (java.io.File)28 HashSet (java.util.HashSet)21 ImmutableSet (com.google.common.collect.ImmutableSet)20 ArtifactNotFoundException (io.cdap.cdap.common.ArtifactNotFoundException)20 Set (java.util.Set)20 Manifest (java.util.jar.Manifest)20 ArtifactId (io.cdap.cdap.api.artifact.ArtifactId)16 PluginNotExistsException (io.cdap.cdap.internal.app.runtime.plugin.PluginNotExistsException)14 PluginId (io.cdap.cdap.proto.id.PluginId)14 ApplicationClass (io.cdap.cdap.api.artifact.ApplicationClass)12 PluginPropertyField (io.cdap.cdap.api.plugin.PluginPropertyField)12 IOException (java.io.IOException)12 ArtifactDetail (io.cdap.cdap.internal.app.runtime.artifact.ArtifactDetail)10