Search in sources :

Example 31 with ApplicationClass

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

the class AbstractProgramRuntimeService method regenerateAppSpec.

/**
 * Regenerates the app spec before the program start
 *
 * @return the regenerated app spec, or null if there is any exception generating the app spec.
 */
@Nullable
private ApplicationSpecification regenerateAppSpec(ArtifactDetail artifactDetail, ProgramId programId, ArtifactId artifactId, ApplicationSpecification existingAppSpec, ProgramOptions options) throws InterruptedException, ExecutionException, TimeoutException {
    ApplicationClass appClass = Iterables.getFirst(artifactDetail.getMeta().getClasses().getApps(), null);
    if (appClass == null) {
        // This should never happen.
        throw new IllegalStateException(String.format("No application class found in artifact '%s' in namespace '%s'.", artifactDetail.getDescriptor().getArtifactId(), programId.getNamespace()));
    }
    AppDeploymentInfo deploymentInfo = new AppDeploymentInfo(artifactId, artifactDetail.getDescriptor().getLocation(), programId.getNamespaceId(), appClass, existingAppSpec.getName(), existingAppSpec.getAppVersion(), existingAppSpec.getConfiguration(), null, false, new AppDeploymentRuntimeInfo(existingAppSpec, options.getUserArguments().asMap(), options.getArguments().asMap()));
    Configurator configurator = this.configuratorFactory.create(deploymentInfo);
    ListenableFuture<ConfigResponse> future = configurator.config();
    ConfigResponse response = future.get(120, TimeUnit.SECONDS);
    if (response.getExitCode() == 0) {
        AppSpecInfo appSpecInfo = response.getAppSpecInfo();
        if (appSpecInfo != null && appSpecInfo.getAppSpec() != null) {
            return appSpecInfo.getAppSpec();
        }
    }
    return null;
}
Also used : AppDeploymentInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentInfo) AppSpecInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppSpecInfo) Configurator(io.cdap.cdap.app.deploy.Configurator) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) ConfigResponse(io.cdap.cdap.app.deploy.ConfigResponse) AppDeploymentRuntimeInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentRuntimeInfo) Nullable(javax.annotation.Nullable)

Example 32 with ApplicationClass

use of io.cdap.cdap.api.artifact.ApplicationClass 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 33 with ApplicationClass

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

the class DefaultArtifactInspector 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 {
        Class<?> mainClass = artifactClassLoader.loadClass(mainClassName);
        if (!(Application.class.isAssignableFrom(mainClass))) {
            // possible for 3rd party plugin artifacts to have the main class set
            return builder;
        }
        Application app = (Application) mainClass.newInstance();
        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, getArtifactRequirements(app.getClass())));
    } 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 : PluginConfig(io.cdap.cdap.api.plugin.PluginConfig) Config(io.cdap.cdap.api.Config) Schema(io.cdap.cdap.api.data.schema.Schema) Attributes(java.util.jar.Attributes) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) ZipException(java.util.zip.ZipException) Manifest(java.util.jar.Manifest) InvalidMetadataException(io.cdap.cdap.common.InvalidMetadataException) ZipException(java.util.zip.ZipException) UnsupportedTypeException(io.cdap.cdap.api.data.schema.UnsupportedTypeException) EOFException(java.io.EOFException) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException) IOException(java.io.IOException) UnsupportedTypeException(io.cdap.cdap.api.data.schema.UnsupportedTypeException) Application(io.cdap.cdap.api.app.Application) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException)

Example 34 with ApplicationClass

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

the class ArtifactStore method getApplicationClasses.

/**
 * Get all application classes that belong to the specified namespace of the specified classname.
 * Results are returned as a sorted map from artifact to application classes in that artifact.
 * Map entries are sorted by the artifact.
 *
 * @param namespace the namespace from which to get application classes
 * @param className the classname of application classes to get
 * @return an unmodifiable map of artifact the application classes in that artifact.
 *         The map will never be null. If there are no application classes, an empty map will be returned.
 */
public SortedMap<ArtifactDescriptor, ApplicationClass> getApplicationClasses(final NamespaceId namespace, final String className) {
    return TransactionRunners.run(transactionRunner, context -> {
        StructuredTable table = getTable(context, StoreDefinition.ArtifactStore.APP_DATA_TABLE);
        SortedMap<ArtifactDescriptor, ApplicationClass> result = Maps.newTreeMap();
        Collection<Field<?>> keys = ImmutableList.of(Fields.stringField(StoreDefinition.ArtifactStore.NAMESPACE_FIELD, namespace.getNamespace()), Fields.stringField(StoreDefinition.ArtifactStore.CLASS_NAME_FIELD, className));
        try (CloseableIterator<StructuredRow> iterator = table.scan(Range.singleton(keys), Integer.MAX_VALUE)) {
            while (iterator.hasNext()) {
                StructuredRow row = iterator.next();
                Map.Entry<ArtifactDescriptor, ApplicationClass> entry = extractApplicationClass(row);
                result.put(entry.getKey(), entry.getValue());
            }
        }
        return Collections.unmodifiableSortedMap(result);
    });
}
Also used : Field(io.cdap.cdap.spi.data.table.field.Field) StructuredTable(io.cdap.cdap.spi.data.StructuredTable) StructuredRow(io.cdap.cdap.spi.data.StructuredRow) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) Map(java.util.Map) SortedMap(java.util.SortedMap) AbstractMap(java.util.AbstractMap) TreeMap(java.util.TreeMap)

Example 35 with ApplicationClass

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

the class ApplicationClassCodec method deserialize.

@Override
public ApplicationClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    JsonObject jsonObject = json.getAsJsonObject();
    Schema configSchema = getConfigSchema(jsonObject, context);
    Requirements requirements = getRequirements(jsonObject, context);
    return new ApplicationClass(getStringValue(jsonObject, CLASS_NAME), getStringValue(jsonObject, DESCRIPTION), configSchema, requirements);
}
Also used : Schema(io.cdap.cdap.api.data.schema.Schema) JsonObject(com.google.gson.JsonObject) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) Requirements(io.cdap.cdap.api.plugin.Requirements)

Aggregations

ApplicationClass (io.cdap.cdap.api.artifact.ApplicationClass)64 Test (org.junit.Test)40 Location (org.apache.twill.filesystem.Location)30 AppDeploymentInfo (io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentInfo)28 ArtifactId (io.cdap.cdap.proto.id.ArtifactId)20 ArtifactVersion (io.cdap.cdap.api.artifact.ArtifactVersion)16 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)16 LocalLocationFactory (org.apache.twill.filesystem.LocalLocationFactory)16 PluginClass (io.cdap.cdap.api.plugin.PluginClass)14 Id (io.cdap.cdap.common.id.Id)14 LocationFactory (org.apache.twill.filesystem.LocationFactory)14 AllProgramsApp (io.cdap.cdap.AllProgramsApp)12 ArtifactId (io.cdap.cdap.api.artifact.ArtifactId)12 Configurator (io.cdap.cdap.app.deploy.Configurator)12 ConfigTestApp (io.cdap.cdap.ConfigTestApp)10 ApplicationSpecification (io.cdap.cdap.api.app.ApplicationSpecification)10 ArtifactRange (io.cdap.cdap.api.artifact.ArtifactRange)10 ArtifactNotFoundException (io.cdap.cdap.common.ArtifactNotFoundException)10 ReflectionSchemaGenerator (io.cdap.cdap.internal.io.ReflectionSchemaGenerator)10 Map (java.util.Map)10