Search in sources :

Example 1 with ApplicationClass

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

the class ArtifactStore method writeMeta.

// write a new artifact snapshot and clean up the old snapshot data
private void writeMeta(Table table, Id.Artifact artifactId, ArtifactData data) throws IOException {
    ArtifactCell artifactCell = new ArtifactCell(artifactId);
    table.put(artifactCell.rowkey, artifactCell.column, Bytes.toBytes(GSON.toJson(data)));
    // column for plugin meta and app meta. {artifact-name}:{artifact-version}
    // does not need to contain namespace because namespace is in the rowkey
    byte[] artifactColumn = new ArtifactColumn(artifactId).getColumn();
    ArtifactClasses classes = data.meta.getClasses();
    Location artifactLocation = Locations.getLocationFromAbsolutePath(locationFactory, data.getLocationPath());
    // write pluginClass metadata
    for (PluginClass pluginClass : classes.getPlugins()) {
        // write metadata for each artifact this plugin extends
        for (ArtifactRange artifactRange : data.meta.getUsableBy()) {
            // p:{namespace}:{type}:{name}
            PluginKey pluginKey = new PluginKey(artifactRange.getNamespace(), artifactRange.getName(), pluginClass.getType(), pluginClass.getName());
            byte[] pluginDataBytes = Bytes.toBytes(GSON.toJson(new PluginData(pluginClass, artifactRange, artifactLocation)));
            table.put(pluginKey.getRowKey(), artifactColumn, pluginDataBytes);
        }
    }
    // write appClass metadata
    for (ApplicationClass appClass : classes.getApps()) {
        // a:{namespace}:{classname}
        AppClassKey appClassKey = new AppClassKey(artifactId.getNamespace().toEntityId(), appClass.getClassName());
        byte[] appDataBytes = Bytes.toBytes(GSON.toJson(new AppData(appClass, artifactLocation)));
        table.put(appClassKey.getRowKey(), artifactColumn, appDataBytes);
    }
}
Also used : ArtifactClasses(co.cask.cdap.api.artifact.ArtifactClasses) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) ApplicationClass(co.cask.cdap.api.artifact.ApplicationClass) PluginClass(co.cask.cdap.api.plugin.PluginClass) Location(org.apache.twill.filesystem.Location)

Example 2 with ApplicationClass

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

the class ArtifactRepository method getApplicationClasses.

/**
   * Get all application classes in the given namespace of the given class name.
   * Will never return null. If no artifacts exist, an empty list is returned. Namespace existence is not checked.
   *
   * @param namespace the namespace to get application classes from
   * @param className the application class to get
   * @return an unmodifiable list of application classes that belong to the given namespace
   * @throws IOException if there as an exception reading from the meta store
   */
public List<ApplicationClassInfo> getApplicationClasses(NamespaceId namespace, String className) throws IOException {
    List<ApplicationClassInfo> infos = Lists.newArrayList();
    for (Map.Entry<ArtifactDescriptor, ApplicationClass> entry : artifactStore.getApplicationClasses(namespace, className).entrySet()) {
        ArtifactSummary artifactSummary = ArtifactSummary.from(entry.getKey().getArtifactId());
        ApplicationClass appClass = entry.getValue();
        infos.add(new ApplicationClassInfo(artifactSummary, appClass.getClassName(), appClass.getConfigSchema()));
    }
    return Collections.unmodifiableList(infos);
}
Also used : ArtifactSummary(co.cask.cdap.api.artifact.ArtifactSummary) ApplicationClassInfo(co.cask.cdap.proto.artifact.ApplicationClassInfo) ApplicationClass(co.cask.cdap.api.artifact.ApplicationClass) Map(java.util.Map) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap)

Example 3 with ApplicationClass

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

the class ArtifactInspector method inspectApplications.

private ArtifactClasses.Builder inspectApplications(Id.Artifact artifactId, ArtifactClasses.Builder builder, Location artifactLocation, ClassLoader artifactClassLoader) throws IOException, InvalidArtifactException {
    // right now we force users to include the application main class as an attribute in their manifest,
    // which forces them to have a single application class.
    // in the future, we may want to let users do this or maybe specify a list of classes or
    // a package that will be searched for applications, to allow multiple applications in a single artifact.
    String mainClassName;
    try {
        Manifest manifest = BundleJarUtil.getManifest(artifactLocation);
        if (manifest == null) {
            return builder;
        }
        Attributes manifestAttributes = manifest.getMainAttributes();
        if (manifestAttributes == null) {
            return builder;
        }
        mainClassName = manifestAttributes.getValue(ManifestFields.MAIN_CLASS);
    } catch (ZipException e) {
        throw new InvalidArtifactException(String.format("Couldn't unzip artifact %s, please check it is a valid jar file.", artifactId), e);
    }
    if (mainClassName == null) {
        return builder;
    }
    try {
        Object appMain = artifactClassLoader.loadClass(mainClassName).newInstance();
        if (!(appMain instanceof Application)) {
            // possible for 3rd party plugin artifacts to have the main class set
            return builder;
        }
        Application app = (Application) appMain;
        java.lang.reflect.Type configType;
        // we can deserialize the config into that object. Otherwise it'll just be a Config
        try {
            configType = Artifacts.getConfigType(app.getClass());
        } catch (Exception e) {
            throw new InvalidArtifactException(String.format("Could not resolve config type for Application class %s in artifact %s. " + "The type must extend Config and cannot be parameterized.", mainClassName, artifactId));
        }
        Schema configSchema = configType == Config.class ? null : schemaGenerator.generate(configType);
        builder.addApp(new ApplicationClass(mainClassName, "", configSchema));
    } catch (ClassNotFoundException e) {
        throw new InvalidArtifactException(String.format("Could not find Application main class %s in artifact %s.", mainClassName, artifactId));
    } catch (UnsupportedTypeException e) {
        throw new InvalidArtifactException(String.format("Config for Application %s in artifact %s has an unsupported schema. " + "The type must extend Config and cannot be parameterized.", mainClassName, artifactId));
    } catch (InstantiationException | IllegalAccessException e) {
        throw new InvalidArtifactException(String.format("Could not instantiate Application class %s in artifact %s.", mainClassName, artifactId), e);
    }
    return builder;
}
Also used : Config(co.cask.cdap.api.Config) PluginConfig(co.cask.cdap.api.plugin.PluginConfig) Schema(co.cask.cdap.api.data.schema.Schema) Attributes(java.util.jar.Attributes) ApplicationClass(co.cask.cdap.api.artifact.ApplicationClass) ZipException(java.util.zip.ZipException) Manifest(java.util.jar.Manifest) ZipException(java.util.zip.ZipException) EOFException(java.io.EOFException) UnsupportedTypeException(co.cask.cdap.api.data.schema.UnsupportedTypeException) IOException(java.io.IOException) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) UnsupportedTypeException(co.cask.cdap.api.data.schema.UnsupportedTypeException) Application(co.cask.cdap.api.app.Application) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException)

Example 4 with ApplicationClass

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

the class ApplicationLifecycleService method deployApp.

private ApplicationWithPrograms deployApp(NamespaceId namespaceId, @Nullable String appName, @Nullable String appVersion, @Nullable String configStr, ProgramTerminator programTerminator, ArtifactDetail artifactDetail, @Nullable KerberosPrincipalId ownerPrincipal, boolean updateSchedules) throws Exception {
    // Enforce that the current principal has write access to the namespace the app is being deployed to
    authorizationEnforcer.enforce(namespaceId, authenticationContext.getPrincipal(), Action.WRITE);
    ApplicationClass appClass = Iterables.getFirst(artifactDetail.getMeta().getClasses().getApps(), null);
    if (appClass == null) {
        throw new InvalidArtifactException(String.format("No application class found in artifact '%s' in namespace '%s'.", artifactDetail.getDescriptor().getArtifactId(), namespaceId));
    }
    // deploy application with newly added artifact
    AppDeploymentInfo deploymentInfo = new AppDeploymentInfo(artifactDetail.getDescriptor(), namespaceId, appClass.getClassName(), appName, appVersion, configStr, ownerPrincipal, updateSchedules);
    Manager<AppDeploymentInfo, ApplicationWithPrograms> manager = managerFactory.create(programTerminator);
    // TODO: (CDAP-3258) Manager needs MUCH better error handling.
    ApplicationWithPrograms applicationWithPrograms;
    try {
        applicationWithPrograms = manager.deploy(deploymentInfo).get();
    } catch (ExecutionException e) {
        Throwables.propagateIfPossible(e.getCause(), Exception.class);
        throw Throwables.propagate(e.getCause());
    }
    // Deployment successful. Grant all privileges on this app to the current principal.
    privilegesManager.grant(applicationWithPrograms.getApplicationId(), authenticationContext.getPrincipal(), EnumSet.allOf(Action.class));
    return applicationWithPrograms;
}
Also used : Action(co.cask.cdap.proto.security.Action) AppDeploymentInfo(co.cask.cdap.internal.app.deploy.pipeline.AppDeploymentInfo) ApplicationWithPrograms(co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) ApplicationClass(co.cask.cdap.api.artifact.ApplicationClass) ExecutionException(java.util.concurrent.ExecutionException) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) CannotBeDeletedException(co.cask.cdap.common.CannotBeDeletedException) ApplicationNotFoundException(co.cask.cdap.common.ApplicationNotFoundException) ArtifactNotFoundException(co.cask.cdap.common.ArtifactNotFoundException) ArtifactAlreadyExistsException(co.cask.cdap.common.ArtifactAlreadyExistsException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) IOException(java.io.IOException) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) ExecutionException(java.util.concurrent.ExecutionException) NotFoundException(co.cask.cdap.common.NotFoundException)

Example 5 with ApplicationClass

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

the class ArtifactStoreTest method testDelete.

@Test
public void testDelete() throws Exception {
    // write an artifact with an app
    Id.Artifact parentId = Id.Artifact.from(Id.Namespace.DEFAULT, "parent", "1.0.0");
    ApplicationClass appClass = new ApplicationClass(InspectionApp.class.getName(), "", new ReflectionSchemaGenerator().generate(InspectionApp.AConfig.class));
    ArtifactMeta artifactMeta = new ArtifactMeta(ArtifactClasses.builder().addApp(appClass).build());
    writeArtifact(parentId, artifactMeta, "parent contents");
    // write a child artifact that extends the parent with some plugins
    Id.Artifact childId = Id.Artifact.from(Id.Namespace.DEFAULT, "myplugins", "1.0.0");
    List<PluginClass> plugins = ImmutableList.of(new PluginClass("atype", "plugin1", "", "c.c.c.plugin1", "cfg", ImmutableMap.<String, PluginPropertyField>of()), new PluginClass("atype", "plugin2", "", "c.c.c.plugin2", "cfg", ImmutableMap.<String, PluginPropertyField>of()));
    Set<ArtifactRange> parents = ImmutableSet.of(new ArtifactRange(parentId.getNamespace().getId(), parentId.getName(), new ArtifactVersion("0.1.0"), new ArtifactVersion("2.0.0")));
    artifactMeta = new ArtifactMeta(ArtifactClasses.builder().addPlugins(plugins).build(), parents);
    writeArtifact(childId, artifactMeta, "child contents");
    // check parent has plugins from the child
    Assert.assertFalse(artifactStore.getPluginClasses(NamespaceId.DEFAULT, parentId).isEmpty());
    // delete the child artifact
    artifactStore.delete(childId);
    // shouldn't be able to get artifact detail
    try {
        artifactStore.getArtifact(childId);
        Assert.fail();
    } catch (ArtifactNotFoundException e) {
    // expected
    }
    // shouldn't see it in the list
    List<ArtifactDetail> artifactList = artifactStore.getArtifacts(parentId.getNamespace().toEntityId());
    Assert.assertEquals(1, artifactList.size());
    Assert.assertEquals(parentId.getName(), artifactList.get(0).getDescriptor().getArtifactId().getName());
    // shouldn't see any more plugins for parent
    Assert.assertTrue(artifactStore.getPluginClasses(NamespaceId.DEFAULT, parentId).isEmpty());
    // delete parent
    artifactStore.delete(parentId);
    // nothing should be in the list
    Assert.assertTrue(artifactStore.getArtifacts(parentId.getNamespace().toEntityId()).isEmpty());
    // shouldn't be able to see app class either
    Assert.assertTrue(artifactStore.getApplicationClasses(NamespaceId.DEFAULT, appClass.getClassName()).isEmpty());
}
Also used : ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) ApplicationClass(co.cask.cdap.api.artifact.ApplicationClass) ReflectionSchemaGenerator(co.cask.cdap.internal.io.ReflectionSchemaGenerator) PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) Id(co.cask.cdap.proto.Id) ArtifactId(co.cask.cdap.proto.id.ArtifactId) NamespaceId(co.cask.cdap.proto.id.NamespaceId) PluginClass(co.cask.cdap.api.plugin.PluginClass) ArtifactNotFoundException(co.cask.cdap.common.ArtifactNotFoundException) InspectionApp(co.cask.cdap.internal.app.runtime.artifact.app.inspection.InspectionApp) Test(org.junit.Test)

Aggregations

ApplicationClass (co.cask.cdap.api.artifact.ApplicationClass)12 PluginClass (co.cask.cdap.api.plugin.PluginClass)7 Test (org.junit.Test)7 Id (co.cask.cdap.proto.Id)6 ArtifactRange (co.cask.cdap.api.artifact.ArtifactRange)5 ReflectionSchemaGenerator (co.cask.cdap.internal.io.ReflectionSchemaGenerator)5 ArtifactId (co.cask.cdap.proto.id.ArtifactId)5 NamespaceId (co.cask.cdap.proto.id.NamespaceId)5 ArtifactNotFoundException (co.cask.cdap.common.ArtifactNotFoundException)4 InspectionApp (co.cask.cdap.internal.app.runtime.artifact.app.inspection.InspectionApp)4 IOException (java.io.IOException)4 ArtifactClasses (co.cask.cdap.api.artifact.ArtifactClasses)3 ArtifactSummary (co.cask.cdap.api.artifact.ArtifactSummary)3 Schema (co.cask.cdap.api.data.schema.Schema)3 PluginPropertyField (co.cask.cdap.api.plugin.PluginPropertyField)3 Manifest (java.util.jar.Manifest)3 ArtifactInfo (co.cask.cdap.api.artifact.ArtifactInfo)2 ArtifactVersion (co.cask.cdap.api.artifact.ArtifactVersion)2 ArtifactAlreadyExistsException (co.cask.cdap.common.ArtifactAlreadyExistsException)2 InvalidArtifactException (co.cask.cdap.common.InvalidArtifactException)2