Search in sources :

Example 1 with ArtifactConfig

use of co.cask.cdap.common.conf.ArtifactConfig in project cdap by caskdata.

the class DefaultArtifactRepository method addSystemArtifacts.

@Override
public void addSystemArtifacts() throws Exception {
    // scan the directory for artifact .jar files and config files for those artifacts
    Map<Id.Artifact, SystemArtifactInfo> systemArtifacts = new HashMap<>();
    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;
            }
            // 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.put(artifactId, new SystemArtifactInfo(artifactId, jarFile, artifactConfig));
            } catch (InvalidArtifactException e) {
                LOG.warn(String.format("Could not add system artifact '%s' because it is invalid.", artifactFileName), e);
            }
        }
    }
    // child -> parents
    Multimap<Id.Artifact, Id.Artifact> childToParents = HashMultimap.create();
    // parent -> children
    Multimap<Id.Artifact, Id.Artifact> parentToChildren = HashMultimap.create();
    Set<Id.Artifact> remainingArtifacts = new HashSet<>();
    // build mapping from child to parents and from parents to children
    for (SystemArtifactInfo child : systemArtifacts.values()) {
        Id.Artifact childId = child.getArtifactId();
        remainingArtifacts.add(childId);
        for (SystemArtifactInfo potentialParent : systemArtifacts.values()) {
            Id.Artifact potentialParentId = potentialParent.getArtifactId();
            // skip if we're looking at ourselves
            if (childId.equals(potentialParentId)) {
                continue;
            }
            if (child.getConfig().hasParent(potentialParentId)) {
                childToParents.put(childId, potentialParentId);
                parentToChildren.put(potentialParentId, childId);
            }
        }
    }
    // loop until there is no change
    boolean nochange = false;
    while (!remainingArtifacts.isEmpty() && !nochange) {
        // add all artifacts that don't have any more parents
        Set<Id.Artifact> addedArtifacts = new HashSet<>();
        for (Id.Artifact remainingArtifact : remainingArtifacts) {
            if (!childToParents.containsKey(remainingArtifact)) {
                addSystemArtifact(systemArtifacts.get(remainingArtifact));
                addedArtifacts.add(remainingArtifact);
                for (Id.Artifact child : parentToChildren.get(remainingArtifact)) {
                    childToParents.remove(child, remainingArtifact);
                }
            }
        }
        remainingArtifacts.removeAll(addedArtifacts);
        nochange = addedArtifacts.isEmpty();
    }
    if (!remainingArtifacts.isEmpty()) {
        LOG.warn("Unable to add system artifacts {} due to cyclic dependencies", Joiner.on(",").join(remainingArtifacts));
    }
}
Also used : HashMap(java.util.HashMap) ArtifactConfig(co.cask.cdap.common.conf.ArtifactConfig) ArtifactId(co.cask.cdap.api.artifact.ArtifactId) Id(co.cask.cdap.common.id.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) File(java.io.File) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) HashSet(java.util.HashSet)

Example 2 with ArtifactConfig

use of co.cask.cdap.common.conf.ArtifactConfig in project cdap by caskdata.

the class LoadArtifactCommand method perform.

@Override
public void perform(Arguments arguments, PrintStream output) throws Exception {
    File artifactFile = resolver.resolvePathToFile(arguments.get(ArgumentName.LOCAL_FILE_PATH.toString()));
    String name = arguments.getOptional(ArgumentName.ARTIFACT_NAME.toString());
    String version = arguments.getOptional(ArgumentName.ARTIFACT_VERSION.toString());
    ArtifactId artifactId;
    if (name == null && version != null) {
        throw new IllegalArgumentException("If a version is specified, name must also be specified.");
    } else if (name != null && version == null) {
        throw new IllegalArgumentException("If a name is specified, a version must also be specified.");
    } else if (name == null) {
        artifactId = new ArtifactId(cliConfig.getCurrentNamespace().getNamespace(), artifactFile.getName());
    } else {
        artifactId = cliConfig.getCurrentNamespace().artifact(name, version);
    }
    String configPath = arguments.getOptional(ArgumentName.ARTIFACT_CONFIG_FILE.toString());
    NamespaceId namespace = artifactId.getParent();
    if (configPath == null) {
        artifactClient.add(namespace, artifactId.getEntityName(), Files.newInputStreamSupplier(artifactFile), artifactId.getVersion());
    } else {
        File configFile = resolver.resolvePathToFile(configPath);
        ArtifactConfig artifactConfig = configReader.read(Id.Namespace.fromEntityId(namespace), configFile);
        artifactClient.add(namespace, artifactId.getEntityName(), Files.newInputStreamSupplier(artifactFile), artifactId.getVersion(), artifactConfig.getParents(), artifactConfig.getPlugins());
        Map<String, String> properties = artifactConfig.getProperties();
        if (properties != null && !properties.isEmpty()) {
            artifactClient.writeProperties(artifactId, properties);
        }
    }
    output.printf("Successfully added artifact with name '%s'\n", artifactId.getEntityName());
}
Also used : ArtifactId(co.cask.cdap.proto.id.ArtifactId) ArtifactConfig(co.cask.cdap.common.conf.ArtifactConfig) NamespaceId(co.cask.cdap.proto.id.NamespaceId) File(java.io.File)

Example 3 with ArtifactConfig

use of co.cask.cdap.common.conf.ArtifactConfig 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 4 with ArtifactConfig

use of co.cask.cdap.common.conf.ArtifactConfig in project cdap by caskdata.

the class ArtifactRepositoryTest method testAddSystemArtifacts.

@Test
public void testAddSystemArtifacts() throws Exception {
    Id.Artifact systemAppArtifactId = Id.Artifact.from(Id.Namespace.SYSTEM, "PluginTest", "1.0.0");
    File systemAppJar = createAppJar(PluginTestApp.class, new File(systemArtifactsDir1, "PluginTest-1.0.0.jar"), createManifest(ManifestFields.EXPORT_PACKAGE, PluginTestRunnable.class.getPackage().getName()));
    // write plugins jar
    Id.Artifact pluginArtifactId1 = Id.Artifact.from(Id.Namespace.SYSTEM, "APlugin", "1.0.0");
    Manifest manifest = createManifest(ManifestFields.EXPORT_PACKAGE, TestPlugin.class.getPackage().getName());
    File pluginJar1 = createPluginJar(TestPlugin.class, new File(systemArtifactsDir1, "APlugin-1.0.0.jar"), manifest);
    // write plugins config file
    Map<String, PluginPropertyField> emptyMap = Collections.emptyMap();
    Set<PluginClass> manuallyAddedPlugins1 = ImmutableSet.of(new PluginClass("typeA", "manual1", "desc", "co.cask.classname", null, emptyMap), new PluginClass("typeB", "manual2", "desc", "co.cask.otherclassname", null, emptyMap));
    File pluginConfigFile = new File(systemArtifactsDir1, "APlugin-1.0.0.json");
    ArtifactConfig pluginConfig1 = new ArtifactConfig(ImmutableSet.of(new ArtifactRange(NamespaceId.SYSTEM.getNamespace(), "PluginTest", new ArtifactVersion("0.9.0"), new ArtifactVersion("2.0.0"))), // add a dummy plugin to test explicit addition of plugins through the config file
    manuallyAddedPlugins1, ImmutableMap.of("k1", "v1", "k2", "v2"));
    try (BufferedWriter writer = Files.newWriter(pluginConfigFile, Charsets.UTF_8)) {
        writer.write(pluginConfig1.toString());
    }
    // write another plugins jar to a different directory, to test that plugins will get picked up from both directories
    Id.Artifact pluginArtifactId2 = Id.Artifact.from(Id.Namespace.SYSTEM, "BPlugin", "1.0.0");
    manifest = createManifest(ManifestFields.EXPORT_PACKAGE, TestPlugin.class.getPackage().getName());
    File pluginJar2 = createPluginJar(TestPlugin.class, new File(systemArtifactsDir2, "BPlugin-1.0.0.jar"), manifest);
    // write plugins config file
    Set<PluginClass> manuallyAddedPlugins2 = ImmutableSet.of(new PluginClass("typeA", "manual1", "desc", "co.notcask.classname", null, emptyMap), new PluginClass("typeB", "manual2", "desc", "co.notcask.otherclassname", null, emptyMap));
    pluginConfigFile = new File(systemArtifactsDir2, "BPlugin-1.0.0.json");
    ArtifactConfig pluginConfig2 = new ArtifactConfig(ImmutableSet.of(new ArtifactRange(NamespaceId.SYSTEM.getNamespace(), "PluginTest", new ArtifactVersion("0.9.0"), new ArtifactVersion("2.0.0"))), manuallyAddedPlugins2, ImmutableMap.of("k3", "v3"));
    try (BufferedWriter writer = Files.newWriter(pluginConfigFile, Charsets.UTF_8)) {
        writer.write(pluginConfig2.toString());
    }
    artifactRepository.addSystemArtifacts();
    Assert.assertTrue(systemAppJar.delete());
    Assert.assertTrue(pluginJar1.delete());
    Assert.assertTrue(pluginJar2.delete());
    try {
        // check app artifact added correctly
        ArtifactDetail appArtifactDetail = artifactRepository.getArtifact(systemAppArtifactId);
        Map<ArtifactDescriptor, Set<PluginClass>> plugins = artifactRepository.getPlugins(NamespaceId.DEFAULT, systemAppArtifactId);
        Assert.assertEquals(2, plugins.size());
        Set<PluginClass> pluginClasses = plugins.values().iterator().next();
        Set<String> pluginNames = Sets.newHashSet();
        for (PluginClass pluginClass : pluginClasses) {
            pluginNames.add(pluginClass.getName());
        }
        Assert.assertEquals(Sets.newHashSet("manual1", "manual2", "TestPlugin", "TestPlugin2"), pluginNames);
        Assert.assertEquals(systemAppArtifactId.getName(), appArtifactDetail.getDescriptor().getArtifactId().getName());
        Assert.assertEquals(systemAppArtifactId.getVersion(), appArtifactDetail.getDescriptor().getArtifactId().getVersion());
        // check plugin artifact added correctly
        ArtifactDetail pluginArtifactDetail = artifactRepository.getArtifact(pluginArtifactId1);
        Assert.assertEquals(pluginArtifactId1.getName(), pluginArtifactDetail.getDescriptor().getArtifactId().getName());
        Assert.assertEquals(pluginArtifactId1.getVersion(), pluginArtifactDetail.getDescriptor().getArtifactId().getVersion());
        // check manually added plugins are there
        Assert.assertTrue(pluginArtifactDetail.getMeta().getClasses().getPlugins().containsAll(manuallyAddedPlugins1));
        // check properties are there
        Assert.assertEquals(pluginConfig1.getProperties(), pluginArtifactDetail.getMeta().getProperties());
        // check other plugin artifact added correctly
        pluginArtifactDetail = artifactRepository.getArtifact(pluginArtifactId2);
        Assert.assertEquals(pluginArtifactId2.getName(), pluginArtifactDetail.getDescriptor().getArtifactId().getName());
        Assert.assertEquals(pluginArtifactId2.getVersion(), pluginArtifactDetail.getDescriptor().getArtifactId().getVersion());
        // check manually added plugins are there
        Assert.assertTrue(pluginArtifactDetail.getMeta().getClasses().getPlugins().containsAll(manuallyAddedPlugins2));
        // check properties are there
        Assert.assertEquals(pluginConfig2.getProperties(), pluginArtifactDetail.getMeta().getProperties());
    } finally {
        artifactRepository.clear(NamespaceId.SYSTEM);
    }
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) HashSet(java.util.HashSet) PluginTestRunnable(co.cask.cdap.internal.app.runtime.artifact.app.plugin.PluginTestRunnable) ArtifactConfig(co.cask.cdap.common.conf.ArtifactConfig) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) Manifest(java.util.jar.Manifest) PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) BufferedWriter(java.io.BufferedWriter) ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) TestPlugin(co.cask.cdap.internal.app.plugins.test.TestPlugin) ArtifactId(co.cask.cdap.api.artifact.ArtifactId) Id(co.cask.cdap.common.id.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) PluginClass(co.cask.cdap.api.plugin.PluginClass) File(java.io.File) Test(org.junit.Test)

Aggregations

ArtifactConfig (co.cask.cdap.common.conf.ArtifactConfig)4 NamespaceId (co.cask.cdap.proto.id.NamespaceId)4 File (java.io.File)4 ArtifactId (co.cask.cdap.api.artifact.ArtifactId)3 HashSet (java.util.HashSet)3 InvalidArtifactException (co.cask.cdap.common.InvalidArtifactException)2 Id (co.cask.cdap.common.id.Id)2 ArtifactRange (co.cask.cdap.api.artifact.ArtifactRange)1 ArtifactVersion (co.cask.cdap.api.artifact.ArtifactVersion)1 PluginClass (co.cask.cdap.api.plugin.PluginClass)1 PluginPropertyField (co.cask.cdap.api.plugin.PluginPropertyField)1 TestPlugin (co.cask.cdap.internal.app.plugins.test.TestPlugin)1 PluginTestRunnable (co.cask.cdap.internal.app.runtime.artifact.app.plugin.PluginTestRunnable)1 Id (co.cask.cdap.proto.Id)1 ArtifactId (co.cask.cdap.proto.id.ArtifactId)1 EntityId (co.cask.cdap.proto.id.EntityId)1 Action (co.cask.cdap.proto.security.Action)1 Principal (co.cask.cdap.proto.security.Principal)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 BufferedWriter (java.io.BufferedWriter)1