Search in sources :

Example 11 with InvalidArtifactException

use of co.cask.cdap.common.InvalidArtifactException in project cdap by caskdata.

the class ApplicationLifecycleService method deployAppAndArtifact.

/**
   * Deploy an application by first adding the application jar to the artifact repository, then creating an application
   * using that newly added artifact.
   *
   * @param namespace the namespace to deploy the application and artifact in
   * @param appName the name of the app. If null, the name will be set based on the application spec
   * @param artifactId the id of the artifact to add and create the application from
   * @param jarFile the application jar to add as an artifact and create the application from
   * @param configStr the configuration to send to the application when generating the application specification
   * @param programTerminator a program terminator that will stop programs that are removed when updating an app.
   *                          For example, if an update removes a flow, the terminator defines how to stop that flow.
   * @return information about the deployed application
   * @throws InvalidArtifactException the the artifact is invalid. For example, if it does not contain any app classes
   * @throws ArtifactAlreadyExistsException if the specified artifact already exists
   * @throws IOException if there was an IO error writing the artifact
   */
public ApplicationWithPrograms deployAppAndArtifact(NamespaceId namespace, @Nullable String appName, Id.Artifact artifactId, File jarFile, @Nullable String configStr, @Nullable KerberosPrincipalId ownerPrincipal, ProgramTerminator programTerminator, boolean updateSchedules) throws Exception {
    ArtifactDetail artifactDetail = artifactRepository.addArtifact(artifactId, jarFile);
    try {
        return deployApp(namespace, appName, null, configStr, programTerminator, artifactDetail, ownerPrincipal, updateSchedules);
    } catch (Exception e) {
        // to the state we were in before this call.
        try {
            artifactRepository.deleteArtifact(artifactId);
        } catch (IOException e2) {
            // if the delete fails, nothing we can do, just log it and continue on
            LOG.warn("Failed to delete artifact {} after deployment of artifact and application failed.", artifactId, e2);
            e.addSuppressed(e2);
        }
        throw e;
    }
}
Also used : IOException(java.io.IOException) 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) ArtifactDetail(co.cask.cdap.internal.app.runtime.artifact.ArtifactDetail)

Example 12 with InvalidArtifactException

use of co.cask.cdap.common.InvalidArtifactException in project cdap by caskdata.

the class ArtifactRepository method validateParentSet.

/**
   * Validates the parents of an artifact. Checks that each artifact only appears with a single version range.
   *
   * @param parents the set of parent ranges to validate
   * @throws InvalidArtifactException if there is more than one version range for an artifact
   */
@VisibleForTesting
static void validateParentSet(Id.Artifact artifactId, Set<ArtifactRange> parents) throws InvalidArtifactException {
    boolean isInvalid = false;
    StringBuilder errMsg = new StringBuilder("Invalid parents field.");
    // check for multiple version ranges for the same artifact.
    // ex: "parents": [ "etlbatch[1.0.0,2.0.0)", "etlbatch[3.0.0,4.0.0)" ]
    Set<String> parentNames = new HashSet<>();
    // keep track of dupes so that we don't have repeat error messages if there are more than 2 ranges for a name
    Set<String> dupes = new HashSet<>();
    for (ArtifactRange parent : parents) {
        String parentName = parent.getName();
        if (!parentNames.add(parentName) && !dupes.contains(parentName)) {
            errMsg.append(" Only one version range for parent '");
            errMsg.append(parentName);
            errMsg.append("' can be present.");
            dupes.add(parentName);
            isInvalid = true;
        }
        if (artifactId.getName().equals(parentName) && artifactId.getNamespace().toEntityId().getNamespace().equals(parent.getNamespace())) {
            throw new InvalidArtifactException(String.format("Invalid parent '%s' for artifact '%s'. An artifact cannot extend itself.", parent, artifactId));
        }
    }
    // "Invalid parents. Only one version range for parent 'etlbatch' can be present."
    if (isInvalid) {
        throw new InvalidArtifactException(errMsg.toString());
    }
}
Also used : ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) HashSet(java.util.HashSet) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 13 with InvalidArtifactException

use of co.cask.cdap.common.InvalidArtifactException in project cdap by caskdata.

the class ArtifactRepository method addSystemArtifacts.

/**
   * Scan all files in the local system artifact directory, looking for jar files and adding them as system artifacts.
   * If the artifact already exists it will not be added again unless it is a snapshot version.
   *
   * @throws IOException if there was some IO error adding the system artifacts
   */
public void addSystemArtifacts() throws Exception {
    // to add system artifacts, users should have write privileges on the system namespace
    Principal principal = authenticationContext.getPrincipal();
    authorizationEnforcer.enforce(NamespaceId.SYSTEM, principal, Action.WRITE);
    // scan the directory for artifact .jar files and config files for those artifacts
    List<SystemArtifactInfo> systemArtifacts = new ArrayList<>();
    for (File systemArtifactDir : systemArtifactDirs) {
        for (File jarFile : DirUtils.listFiles(systemArtifactDir, "jar")) {
            // parse id from filename
            Id.Artifact artifactId;
            try {
                artifactId = Id.Artifact.parse(Id.Namespace.SYSTEM, jarFile.getName());
            } catch (IllegalArgumentException e) {
                LOG.warn(String.format("Skipping system artifact '%s' because the name is invalid: ", e.getMessage()));
                continue;
            }
            // first revoke any orphane privileges
            co.cask.cdap.proto.id.ArtifactId artifact = artifactId.toEntityId();
            privilegesManager.revoke(artifact);
            // then grant all on the artifact
            privilegesManager.grant(artifact, principal, EnumSet.allOf(Action.class));
            // check for a corresponding .json config file
            String artifactFileName = jarFile.getName();
            String configFileName = artifactFileName.substring(0, artifactFileName.length() - ".jar".length()) + ".json";
            File configFile = new File(systemArtifactDir, configFileName);
            try {
                // read and parse the config file if it exists. Otherwise use an empty config with the artifact filename
                ArtifactConfig artifactConfig = configFile.isFile() ? configReader.read(artifactId.getNamespace(), configFile) : new ArtifactConfig();
                validateParentSet(artifactId, artifactConfig.getParents());
                validatePluginSet(artifactConfig.getPlugins());
                systemArtifacts.add(new SystemArtifactInfo(artifactId, jarFile, artifactConfig));
            } catch (InvalidArtifactException e) {
                LOG.warn(String.format("Could not add system artifact '%s' because it is invalid.", artifactFileName), e);
                // since adding artifact failed, revoke privileges, since they may be orphane now
                privilegesManager.revoke(artifact);
            }
        }
    }
    // taking advantage of the fact that we only have 1 level of dependencies
    // so we can add all the parents first, then we know its safe to add everything else
    // add all parents
    Set<Id.Artifact> parents = new HashSet<>();
    for (SystemArtifactInfo child : systemArtifacts) {
        Id.Artifact childId = child.getArtifactId();
        for (SystemArtifactInfo potentialParent : systemArtifacts) {
            Id.Artifact potentialParentId = potentialParent.getArtifactId();
            // skip if we're looking at ourselves
            if (childId.equals(potentialParentId)) {
                continue;
            }
            if (child.getConfig().hasParent(potentialParentId)) {
                parents.add(potentialParentId);
            }
        }
    }
    // add all parents first
    for (SystemArtifactInfo systemArtifact : systemArtifacts) {
        if (parents.contains(systemArtifact.getArtifactId())) {
            addSystemArtifact(systemArtifact);
        }
    }
    // add children next
    for (SystemArtifactInfo systemArtifact : systemArtifacts) {
        if (!parents.contains(systemArtifact.getArtifactId())) {
            addSystemArtifact(systemArtifact);
        }
    }
}
Also used : Action(co.cask.cdap.proto.security.Action) ArtifactConfig(co.cask.cdap.common.conf.ArtifactConfig) ArrayList(java.util.ArrayList) ArtifactId(co.cask.cdap.api.artifact.ArtifactId) Id(co.cask.cdap.proto.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) EntityId(co.cask.cdap.proto.id.EntityId) File(java.io.File) Principal(co.cask.cdap.proto.security.Principal) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) HashSet(java.util.HashSet)

Example 14 with InvalidArtifactException

use of co.cask.cdap.common.InvalidArtifactException in project cdap by caskdata.

the class ArtifactRepository method validatePluginSet.

/**
   * Validates the set of plugins for an artifact. Checks that the pair of plugin type and name are unique among
   * all plugins in an artifact.
   *
   * @param plugins the set of plugins to validate
   * @throws InvalidArtifactException if there is more than one class with the same type and name
   */
@VisibleForTesting
static void validatePluginSet(Set<PluginClass> plugins) throws InvalidArtifactException {
    boolean isInvalid = false;
    StringBuilder errMsg = new StringBuilder("Invalid plugins field.");
    Set<ImmutablePair<String, String>> existingPlugins = new HashSet<>();
    Set<ImmutablePair<String, String>> dupes = new HashSet<>();
    for (PluginClass plugin : plugins) {
        ImmutablePair<String, String> typeAndName = ImmutablePair.of(plugin.getType(), plugin.getName());
        if (!existingPlugins.add(typeAndName) && !dupes.contains(typeAndName)) {
            errMsg.append(" Only one plugin with type '");
            errMsg.append(typeAndName.getFirst());
            errMsg.append("' and name '");
            errMsg.append(typeAndName.getSecond());
            errMsg.append("' can be present.");
            dupes.add(typeAndName);
            isInvalid = true;
        }
    }
    // "Invalid plugins. Only one plugin with type 'source' and name 'table' can be present."
    if (isInvalid) {
        throw new InvalidArtifactException(errMsg.toString());
    }
}
Also used : ImmutablePair(co.cask.cdap.common.utils.ImmutablePair) PluginClass(co.cask.cdap.api.plugin.PluginClass) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) HashSet(java.util.HashSet) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

InvalidArtifactException (co.cask.cdap.common.InvalidArtifactException)14 IOException (java.io.IOException)8 ApplicationNotFoundException (co.cask.cdap.common.ApplicationNotFoundException)6 ArtifactAlreadyExistsException (co.cask.cdap.common.ArtifactAlreadyExistsException)5 ArtifactNotFoundException (co.cask.cdap.common.ArtifactNotFoundException)5 NotFoundException (co.cask.cdap.common.NotFoundException)5 UnauthorizedException (co.cask.cdap.security.spi.authorization.UnauthorizedException)5 ExecutionException (java.util.concurrent.ExecutionException)5 JsonSyntaxException (com.google.gson.JsonSyntaxException)4 File (java.io.File)4 BadRequestException (co.cask.cdap.common.BadRequestException)3 ConflictException (co.cask.cdap.common.ConflictException)3 NamespaceNotFoundException (co.cask.cdap.common.NamespaceNotFoundException)3 WriteConflictException (co.cask.cdap.internal.app.runtime.artifact.WriteConflictException)3 Id (co.cask.cdap.proto.Id)3 ApplicationId (co.cask.cdap.proto.id.ApplicationId)3 EntityId (co.cask.cdap.proto.id.EntityId)3 KerberosPrincipalId (co.cask.cdap.proto.id.KerberosPrincipalId)3 NamespaceId (co.cask.cdap.proto.id.NamespaceId)3 HashSet (java.util.HashSet)3