use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactRepository method addArtifact.
/**
* Inspects and builds plugin and application information for the given artifact, adding an additional set of
* plugin classes to the plugins found through inspection. This method is used when all plugin classes
* cannot be derived by inspecting the artifact but need to be explicitly set. This is true for 3rd party plugins
* like jdbc drivers.
*
* @param artifactId the id of the artifact to inspect and store
* @param artifactFile the artifact to inspect and store
* @param parentArtifacts artifacts the given artifact extends.
* If null, the given artifact does not extend another artifact
* @param additionalPlugins the set of additional plugin classes to add to the plugins found through inspection.
* If null, no additional plugin classes will be added
* @param properties properties for the artifact
* @throws IOException if there was an exception reading from the artifact store
* @throws ArtifactRangeNotFoundException if none of the parent artifacts could be found
* @throws UnauthorizedException if the user is not authorized to add an artifact in the specified namespace. To add
* an artifact, a user must have {@link Action#WRITE} on the namespace in which
* the artifact is being added. If authorization is successful, and
* the artifact is added successfully, then the user gets all {@link Action privileges}
* on the added artifact.
*/
@VisibleForTesting
public ArtifactDetail addArtifact(final Id.Artifact artifactId, final File artifactFile, @Nullable Set<ArtifactRange> parentArtifacts, @Nullable Set<PluginClass> additionalPlugins, Map<String, String> properties) throws Exception {
if (additionalPlugins != null) {
validatePluginSet(additionalPlugins);
}
parentArtifacts = parentArtifacts == null ? Collections.<ArtifactRange>emptySet() : parentArtifacts;
CloseableClassLoader parentClassLoader = null;
EntityImpersonator entityImpersonator = new EntityImpersonator(artifactId.toEntityId(), impersonator);
if (!parentArtifacts.isEmpty()) {
validateParentSet(artifactId, parentArtifacts);
parentClassLoader = createParentClassLoader(artifactId, parentArtifacts, entityImpersonator);
}
try {
ArtifactClasses artifactClasses = inspectArtifact(artifactId, artifactFile, additionalPlugins, parentClassLoader);
ArtifactMeta meta = new ArtifactMeta(artifactClasses, parentArtifacts, properties);
ArtifactDetail artifactDetail = artifactStore.write(artifactId, meta, Files.newInputStreamSupplier(artifactFile), entityImpersonator);
ArtifactDescriptor descriptor = artifactDetail.getDescriptor();
// info hides some fields that are available in detail, such as the location of the artifact
ArtifactInfo artifactInfo = new ArtifactInfo(descriptor.getArtifactId(), artifactDetail.getMeta().getClasses(), artifactDetail.getMeta().getProperties());
// add system metadata for artifacts
writeSystemMetadata(artifactId.toEntityId(), artifactInfo);
return artifactDetail;
} finally {
Closeables.closeQuietly(parentClassLoader);
}
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactHttpHandlerTest method testGetPlugins.
@Test
public void testGetPlugins() 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, "wordcount", "2.0.0");
Assert.assertEquals(HttpResponseStatus.OK.getCode(), addAppArtifact(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());
Id.Artifact pluginsId1 = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(pluginsId1, Plugin1.class, manifest, plugins1Parents).getStatusLine().getStatusCode());
// plugin-2.0.0 extends wordcount[1.0.0,3.0.0)
Id.Artifact pluginsId2 = Id.Artifact.from(Id.Namespace.DEFAULT, "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.getCode(), addPluginArtifact(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(), plugins1Artifact, p1Properties, new HashSet<String>()), new PluginInfo("Plugin1", "dummy", "This is plugin1", Plugin1.class.getName(), plugins2Artifact, p1Properties, new HashSet<String>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount1Id, "dummy", "Plugin1"));
expectedInfos = Sets.newHashSet(new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins1Artifact, p2Properties, new HashSet<String>()), new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins2Artifact, p2Properties, new HashSet<String>()));
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(), plugins2Artifact, p1Properties, new HashSet<String>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount2Id, "dummy", "Plugin1"));
expectedInfos = Sets.newHashSet(new PluginInfo("Plugin2", "callable", "Just returns the configured integer", Plugin2.class.getName(), plugins2Artifact, p2Properties, new HashSet<String>()));
Assert.assertEquals(expectedInfos, getPluginInfos(wordCount2Id, "callable", "Plugin2"));
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactStoreTest method testGetNonexistantArtifact.
@Test
public void testGetNonexistantArtifact() throws IOException {
NamespaceId namespace = Ids.namespace("ns1");
// no artifacts in a namespace should return an empty collection
Assert.assertTrue(artifactStore.getArtifacts(namespace).isEmpty());
// no artifacts in range should return an empty collection
ArtifactRange range = new ArtifactRange(namespace.getNamespace(), "something", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0"));
Assert.assertTrue(artifactStore.getArtifacts(range, Integer.MAX_VALUE, ArtifactSortOrder.UNORDERED).isEmpty());
// no artifact by namespace and artifact name should throw an exception
try {
artifactStore.getArtifacts(namespace, "something", Integer.MAX_VALUE, ArtifactSortOrder.UNORDERED);
Assert.fail();
} catch (ArtifactNotFoundException e) {
// expected
}
// no artifact by namespace, artifact name, and version should throw an exception
try {
artifactStore.getArtifact(Id.Artifact.from(namespace.toId(), "something", "1.0.0"));
Assert.fail();
} catch (ArtifactNotFoundException e) {
// expected
}
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactClientTestRun method testAddSelfExtendingThrowsBadRequest.
@Test
public void testAddSelfExtendingThrowsBadRequest() throws Exception {
try {
artifactClient.add(NamespaceId.DEFAULT, "abc", DUMMY_SUPPLIER, "1.0.0", Sets.newHashSet(new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "abc", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0"))));
Assert.fail();
} catch (BadRequestException e) {
// expected
}
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactClientTestRun method testArtifacts.
@Test
public void testArtifacts() throws Exception {
// add 2 versions of an artifact with an application
ArtifactId myapp1Id = NamespaceId.DEFAULT.artifact("myapp", "1.0.0");
ArtifactId myapp2Id = NamespaceId.DEFAULT.artifact("myapp", "2.0.0");
LocalLocationFactory locationFactory = new LocalLocationFactory(TMP_FOLDER.newFolder());
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.BUNDLE_VERSION, "2.0.0");
final Location appJarLoc = AppJarHelper.createDeploymentJar(locationFactory, MyApp.class, manifest);
InputSupplier<InputStream> inputSupplier = new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return appJarLoc.getInputStream();
}
};
artifactClient.add(myapp1Id.getParent(), myapp1Id.getArtifact(), inputSupplier, myapp1Id.getVersion());
// add some properties
Map<String, String> myapp1Properties = ImmutableMap.of("k1", "v1");
artifactClient.writeProperties(myapp1Id, myapp1Properties);
// let it derive version from jar manifest, which has bundle-version at 2.0.0
artifactClient.add(myapp2Id.getParent(), myapp2Id.getArtifact(), inputSupplier, null, null);
// add some properties
Map<String, String> myapp2Properties = ImmutableMap.of("k1", "v1", "k2", "v2");
artifactClient.writeProperties(myapp2Id, myapp2Properties);
// add an artifact that contains a plugin, but only extends myapp-2.0.0
ArtifactId pluginId = NamespaceId.DEFAULT.artifact("myapp-plugins", "2.0.0");
manifest = new Manifest();
manifest.getMainAttributes().put(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
final Location pluginJarLoc = PluginJarHelper.createPluginJar(locationFactory, manifest, Plugin1.class);
inputSupplier = new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return pluginJarLoc.getInputStream();
}
};
Set<ArtifactRange> parents = Sets.newHashSet(new ArtifactRange(myapp2Id.getParent().getNamespace(), myapp2Id.getArtifact(), new ArtifactVersion(myapp2Id.getVersion()), new ArtifactVersion("3.0.0")));
Set<PluginClass> additionalPlugins = Sets.newHashSet(new PluginClass("jdbc", "mysql", "", "com.mysql.jdbc.Driver", null, Collections.<String, PluginPropertyField>emptyMap()));
artifactClient.add(pluginId.getParent(), pluginId.getArtifact(), inputSupplier, pluginId.getVersion(), parents, additionalPlugins);
ArtifactSummary myapp1Summary = new ArtifactSummary(myapp1Id.getArtifact(), myapp1Id.getVersion());
ArtifactSummary myapp2Summary = new ArtifactSummary(myapp2Id.getArtifact(), myapp2Id.getVersion());
ArtifactSummary pluginArtifactSummary = new ArtifactSummary(pluginId.getArtifact(), pluginId.getVersion());
Set<ArtifactSummary> artifacts = Sets.newHashSet(artifactClient.list(NamespaceId.DEFAULT));
Assert.assertEquals(Sets.newHashSet(myapp1Summary, myapp2Summary, pluginArtifactSummary), artifacts);
// list all artifacts named 'myapp'
Assert.assertEquals(Sets.newHashSet(myapp1Summary, myapp2Summary), Sets.newHashSet(artifactClient.listVersions(NamespaceId.DEFAULT, myapp1Id.getArtifact())));
// list all artifacts named 'myapp-plugins'
Assert.assertEquals(Sets.newHashSet(pluginArtifactSummary), Sets.newHashSet(artifactClient.listVersions(NamespaceId.DEFAULT, pluginId.getArtifact())));
// artifacts should be in user scope
try {
artifactClient.listVersions(NamespaceId.DEFAULT, pluginId.getArtifact(), ArtifactScope.SYSTEM);
Assert.fail();
} catch (ArtifactNotFoundException e) {
// expected
}
// get info about specific artifacts
Schema myAppConfigSchema = new ReflectionSchemaGenerator(false).generate(MyApp.Conf.class);
ArtifactClasses myAppClasses = ArtifactClasses.builder().addApp(new ApplicationClass(MyApp.class.getName(), "", myAppConfigSchema)).build();
// test get myapp-1.0.0
ArtifactInfo myapp1Info = new ArtifactInfo(myapp1Id.getArtifact(), myapp1Id.getVersion(), ArtifactScope.USER, myAppClasses, myapp1Properties);
Assert.assertEquals(myapp1Info, artifactClient.getArtifactInfo(myapp1Id));
// test get myapp-2.0.0
ArtifactInfo myapp2Info = new ArtifactInfo(myapp2Id.getArtifact(), myapp2Id.getVersion(), ArtifactScope.USER, myAppClasses, myapp2Properties);
Assert.assertEquals(myapp2Info, artifactClient.getArtifactInfo(myapp2Id));
// test overwriting properties
myapp2Properties = ImmutableMap.of("k1", "v3", "k5", "v5");
artifactClient.writeProperties(myapp2Id, myapp2Properties);
Assert.assertEquals(myapp2Properties, artifactClient.getArtifactInfo(myapp2Id).getProperties());
// test deleting property
artifactClient.deleteProperty(myapp2Id, "k1");
Assert.assertEquals(ImmutableMap.of("k5", "v5"), artifactClient.getArtifactInfo(myapp2Id).getProperties());
// test writing property
artifactClient.writeProperty(myapp2Id, "k5", "v4");
Assert.assertEquals(ImmutableMap.of("k5", "v4"), artifactClient.getArtifactInfo(myapp2Id).getProperties());
// test deleting properties
artifactClient.deleteProperties(myapp2Id);
Assert.assertTrue(artifactClient.getArtifactInfo(myapp2Id).getProperties().isEmpty());
// test get myapp-plugins-2.0.0
Map<String, PluginPropertyField> props = ImmutableMap.of("x", new PluginPropertyField("x", "", "int", true, false));
ArtifactClasses pluginClasses = ArtifactClasses.builder().addPlugin(new PluginClass("callable", "plugin1", "p1 description", Plugin1.class.getName(), "conf", props)).addPlugins(additionalPlugins).build();
ArtifactInfo pluginArtifactInfo = new ArtifactInfo(pluginId.getArtifact(), pluginId.getVersion(), ArtifactScope.USER, pluginClasses, ImmutableMap.<String, String>of());
Assert.assertEquals(pluginArtifactInfo, artifactClient.getArtifactInfo(pluginId));
// test get all app classes in namespace
Set<ApplicationClassSummary> expectedSummaries = ImmutableSet.of(new ApplicationClassSummary(myapp1Summary, MyApp.class.getName()), new ApplicationClassSummary(myapp2Summary, MyApp.class.getName()));
Set<ApplicationClassSummary> appClassSummaries = Sets.newHashSet(artifactClient.getApplicationClasses(NamespaceId.DEFAULT));
Assert.assertEquals(expectedSummaries, appClassSummaries);
// test get all app classes in namespace with name MyApp.class.getName()
Set<ApplicationClassInfo> appClassInfos = Sets.newHashSet(artifactClient.getApplicationClasses(NamespaceId.DEFAULT, MyApp.class.getName()));
Set<ApplicationClassInfo> expectedInfos = ImmutableSet.of(new ApplicationClassInfo(myapp1Summary, MyApp.class.getName(), myAppConfigSchema), new ApplicationClassInfo(myapp2Summary, MyApp.class.getName(), myAppConfigSchema));
Assert.assertEquals(expectedInfos, appClassInfos);
// test get plugin types for myapp-1.0.0. should be empty, since plugins only extends versions [2.0.0 - 3.0.0)
Assert.assertTrue(artifactClient.getPluginTypes(myapp1Id).isEmpty());
// test get plugin types for myapp-2.0.0
Assert.assertEquals(Lists.newArrayList("callable", "jdbc"), artifactClient.getPluginTypes(myapp2Id));
// test get plugins of type callable for myapp-2.0.0
PluginSummary pluginSummary = new PluginSummary("plugin1", "callable", "p1 description", Plugin1.class.getName(), pluginArtifactSummary);
Assert.assertEquals(Sets.newHashSet(pluginSummary), Sets.newHashSet(artifactClient.getPluginSummaries(myapp2Id, "callable")));
// no plugins of type "runnable"
Assert.assertTrue(artifactClient.getPluginSummaries(myapp2Id, "runnable").isEmpty());
// test get plugin details for plugin1 for myapp-2.0.0
PluginInfo pluginInfo = new PluginInfo("plugin1", "callable", "p1 description", Plugin1.class.getName(), pluginArtifactSummary, props, new HashSet<String>());
Assert.assertEquals(Sets.newHashSet(pluginInfo), Sets.newHashSet(artifactClient.getPluginInfo(myapp2Id, "callable", "plugin1")));
}
Aggregations