Search in sources :

Example 6 with ApplicationClass

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

the class DefaultArtifactInspectorTest method inspectAppsAndPlugins.

@Test
public void inspectAppsAndPlugins() throws Exception {
    File appFile = getAppFile();
    Id.Artifact artifactId = Id.Artifact.from(Id.Namespace.DEFAULT, "InspectionApp", "1.0.0");
    Location artifactLocation = Locations.toLocation(appFile);
    List<ArtifactDescriptor> parentDescriptor = new ArrayList<>();
    parentDescriptor.add(new ArtifactDescriptor(artifactId.getNamespace().getId(), artifactId.toArtifactId(), artifactLocation));
    ArtifactClasses classes = artifactInspector.inspectArtifact(artifactId, appFile, parentDescriptor, Collections.emptySet()).getArtifactClasses();
    // check app classes
    Set<ApplicationClass> expectedApps = ImmutableSet.of(new ApplicationClass(InspectionApp.class.getName(), "", new ReflectionSchemaGenerator(false).generate(InspectionApp.AConfig.class), new Requirements(Collections.emptySet(), Collections.singleton("cdc"))));
    Assert.assertEquals(expectedApps, classes.getApps());
    // check plugin classes
    PluginClass expectedPlugin = PluginClass.builder().setName(InspectionApp.PLUGIN_NAME).setType(InspectionApp.PLUGIN_TYPE).setDescription(InspectionApp.PLUGIN_DESCRIPTION).setClassName(InspectionApp.AppPlugin.class.getName()).setConfigFieldName("pluginConf").setProperties(ImmutableMap.of("y", new PluginPropertyField("y", "", "double", true, true), "isSomething", new PluginPropertyField("isSomething", "", "boolean", true, false))).build();
    PluginClass multipleRequirementPlugin = PluginClass.builder().setName(InspectionApp.MULTIPLE_REQUIREMENTS_PLUGIN).setType(InspectionApp.PLUGIN_TYPE).setCategory(InspectionApp.PLUGIN_CATEGORY).setClassName(InspectionApp.MultipleRequirementsPlugin.class.getName()).setConfigFieldName("pluginConf").setProperties(ImmutableMap.of("y", new PluginPropertyField("y", "", "double", true, true), "isSomething", new PluginPropertyField("isSomething", "", "boolean", true, false))).setRequirements(new Requirements(ImmutableSet.of(Table.TYPE, KeyValueTable.TYPE))).setDescription(InspectionApp.PLUGIN_DESCRIPTION).build();
    Assert.assertTrue(classes.getPlugins().containsAll(ImmutableSet.of(expectedPlugin, multipleRequirementPlugin)));
}
Also used : ArrayList(java.util.ArrayList) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) ReflectionSchemaGenerator(io.cdap.cdap.internal.io.ReflectionSchemaGenerator) PluginPropertyField(io.cdap.cdap.api.plugin.PluginPropertyField) Requirements(io.cdap.cdap.api.plugin.Requirements) ArtifactClasses(io.cdap.cdap.api.artifact.ArtifactClasses) Id(io.cdap.cdap.common.id.Id) PluginClass(io.cdap.cdap.api.plugin.PluginClass) File(java.io.File) Location(org.apache.twill.filesystem.Location) InspectionApp(io.cdap.cdap.internal.app.runtime.artifact.app.inspection.InspectionApp) Test(org.junit.Test)

Example 7 with ApplicationClass

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

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 8 with ApplicationClass

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

the class ApplicationLifecycleService method updateApplicationInternal.

/**
 * Updates an application config by applying given update actions. The app should know how to apply these actions
 * to its config.
 */
private void updateApplicationInternal(ApplicationId appId, @Nullable String currentConfigStr, ProgramTerminator programTerminator, ArtifactDetail artifactDetail, List<ApplicationConfigUpdateAction> updateActions, Set<ArtifactScope> allowedArtifactScopes, boolean allowSnapshot, @Nullable KerberosPrincipalId ownerPrincipal, boolean updateSchedules) throws Exception {
    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(), appId.getParent()));
    }
    io.cdap.cdap.proto.id.ArtifactId artifactId = Artifacts.toProtoArtifactId(appId.getParent(), artifactDetail.getDescriptor().getArtifactId());
    EntityImpersonator classLoaderImpersonator = new EntityImpersonator(artifactId, this.impersonator);
    String updatedAppConfig;
    DefaultApplicationUpdateContext updateContext = new DefaultApplicationUpdateContext(appId.getParent(), appId, artifactDetail.getDescriptor().getArtifactId(), artifactRepository, currentConfigStr, updateActions, allowedArtifactScopes, allowSnapshot);
    try (CloseableClassLoader artifactClassLoader = artifactRepository.createArtifactClassLoader(artifactDetail.getDescriptor(), classLoaderImpersonator)) {
        Object appMain = artifactClassLoader.loadClass(appClass.getClassName()).newInstance();
        // Run config update logic for the application to generate updated config.
        if (!(appMain instanceof Application)) {
            throw new IllegalStateException(String.format("Application main class is of invalid type: %s", appMain.getClass().getName()));
        }
        Application app = (Application) appMain;
        Type configType = Artifacts.getConfigType(app.getClass());
        if (!app.isUpdateSupported()) {
            String errorMessage = String.format("Application %s does not support update.", appId);
            throw new UnsupportedOperationException(errorMessage);
        }
        ApplicationUpdateResult<?> updateResult = app.updateConfig(updateContext);
        updatedAppConfig = GSON.toJson(updateResult.getNewConfig(), configType);
    }
    // Deploy application with with potentially new app config and new artifact.
    AppDeploymentInfo deploymentInfo = new AppDeploymentInfo(artifactId, artifactDetail.getDescriptor().getLocation(), appId.getParent(), appClass, appId.getApplication(), appId.getVersion(), updatedAppConfig, ownerPrincipal, updateSchedules, null);
    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());
    }
    adminEventPublisher.publishAppCreation(applicationWithPrograms.getApplicationId(), applicationWithPrograms.getSpecification());
}
Also used : DefaultApplicationUpdateContext(io.cdap.cdap.internal.app.DefaultApplicationUpdateContext) EntityImpersonator(io.cdap.cdap.security.impersonation.EntityImpersonator) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) CloseableClassLoader(io.cdap.cdap.api.artifact.CloseableClassLoader) ApplicationNotFoundException(io.cdap.cdap.common.ApplicationNotFoundException) CapabilityNotAvailableException(io.cdap.cdap.internal.capability.CapabilityNotAvailableException) IOException(java.io.IOException) CannotBeDeletedException(io.cdap.cdap.common.CannotBeDeletedException) ExecutionException(java.util.concurrent.ExecutionException) AccessException(io.cdap.cdap.api.security.AccessException) JsonIOException(com.google.gson.JsonIOException) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException) ArtifactAlreadyExistsException(io.cdap.cdap.common.ArtifactAlreadyExistsException) NotFoundException(io.cdap.cdap.common.NotFoundException) ArtifactNotFoundException(io.cdap.cdap.common.ArtifactNotFoundException) EntityType(io.cdap.cdap.proto.element.EntityType) Type(java.lang.reflect.Type) ProgramType(io.cdap.cdap.proto.ProgramType) AppDeploymentInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentInfo) ApplicationWithPrograms(io.cdap.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) ExecutionException(java.util.concurrent.ExecutionException) Application(io.cdap.cdap.api.app.Application)

Example 9 with ApplicationClass

use of io.cdap.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, boolean isPreview, Map<String, String> userProps) throws Exception {
    // Now to deploy an app, we need ADMIN privilege on the owner principal if it is present, and also ADMIN on the app
    // But since at this point, app name is unknown to us, so the enforcement on the app is happening in the deploy
    // pipeline - LocalArtifactLoaderStage
    // need to enforce on the principal id if impersonation is involved
    KerberosPrincipalId effectiveOwner = SecurityUtil.getEffectiveOwner(ownerAdmin, namespaceId, ownerPrincipal == null ? null : ownerPrincipal.getPrincipal());
    Principal requestingUser = authenticationContext.getPrincipal();
    // impersonated principal
    if (effectiveOwner != null) {
        accessEnforcer.enforce(effectiveOwner, requestingUser, AccessPermission.SET_OWNER);
    }
    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));
    }
    if (!NamespaceId.SYSTEM.equals(namespaceId)) {
        capabilityReader.checkAllEnabled(appClass.getRequirements().getCapabilities());
    }
    // deploy application with newly added artifact
    AppDeploymentInfo deploymentInfo = new AppDeploymentInfo(Artifacts.toProtoArtifactId(namespaceId, artifactDetail.getDescriptor().getArtifactId()), artifactDetail.getDescriptor().getLocation(), namespaceId, appClass, appName, appVersion, configStr, ownerPrincipal, updateSchedules, isPreview ? new AppDeploymentRuntimeInfo(null, userProps, Collections.emptyMap()) : null);
    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());
    }
    adminEventPublisher.publishAppCreation(applicationWithPrograms.getApplicationId(), applicationWithPrograms.getSpecification());
    return applicationWithPrograms;
}
Also used : AppDeploymentInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentInfo) ApplicationWithPrograms(io.cdap.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) ApplicationClass(io.cdap.cdap.api.artifact.ApplicationClass) ExecutionException(java.util.concurrent.ExecutionException) KerberosPrincipalId(io.cdap.cdap.proto.id.KerberosPrincipalId) Principal(io.cdap.cdap.proto.security.Principal) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException) ApplicationNotFoundException(io.cdap.cdap.common.ApplicationNotFoundException) CapabilityNotAvailableException(io.cdap.cdap.internal.capability.CapabilityNotAvailableException) IOException(java.io.IOException) CannotBeDeletedException(io.cdap.cdap.common.CannotBeDeletedException) ExecutionException(java.util.concurrent.ExecutionException) AccessException(io.cdap.cdap.api.security.AccessException) JsonIOException(com.google.gson.JsonIOException) InvalidArtifactException(io.cdap.cdap.common.InvalidArtifactException) ArtifactAlreadyExistsException(io.cdap.cdap.common.ArtifactAlreadyExistsException) NotFoundException(io.cdap.cdap.common.NotFoundException) ArtifactNotFoundException(io.cdap.cdap.common.ArtifactNotFoundException) AppDeploymentRuntimeInfo(io.cdap.cdap.internal.app.deploy.pipeline.AppDeploymentRuntimeInfo)

Example 10 with ApplicationClass

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

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)

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