Search in sources :

Example 1 with KojiTagInfo

use of com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo in project indy by Commonjava.

the class KojiMavenMetadataProvider method getMetadata.

@Override
@IndyMetrics(measure = @Measure(timers = @MetricNamed(name = IndyMetricsKojiNames.METHOD_MAVENMETADATA_GETMETADATA + IndyMetricsNames.TIMER), meters = @MetricNamed(name = IndyMetricsKojiNames.METHOD_MAVENMETADATA_GETMETADATA + IndyMetricsNames.METER)))
public Metadata getMetadata(StoreKey targetKey, String path) throws IndyWorkflowException {
    Logger logger = LoggerFactory.getLogger(getClass());
    if (group != targetKey.getType()) {
        logger.debug("Not a group. Cannot supplement with metadata from Koji builds");
        return null;
    }
    if (!kojiConfig.isEnabled()) {
        logger.debug("Koji add-on is disabled.");
        return null;
    }
    if (!kojiConfig.isEnabledFor(targetKey.getName())) {
        logger.debug("Koji integration is not enabled for group: {}", targetKey);
        return null;
    }
    File mdFile = new File(path);
    File artifactDir = mdFile.getParentFile();
    File groupDir = artifactDir == null ? null : artifactDir.getParentFile();
    if (artifactDir == null || groupDir == null) {
        logger.debug("Invalid groupId / artifactId directory structure: '{}' / '{}'", groupDir, artifactDir);
        return null;
    }
    String groupId = groupDir.getPath().replace(File.separatorChar, '.');
    String artifactId = artifactDir.getName();
    ProjectRef ga = null;
    try {
        ga = new SimpleProjectRef(groupId, artifactId);
    } catch (InvalidRefException e) {
        logger.debug("Not a valid Maven GA: {}:{}. Skipping Koji metadata retrieval.", groupId, artifactId);
    }
    if (ga == null) {
        logger.debug("Could not render a valid Maven GA for path: '{}'", path);
        return null;
    }
    ReentrantLock lock;
    synchronized (versionMetadataLocks) {
        lock = versionMetadataLocks.get(ga);
        if (lock == null) {
            lock = new ReentrantLock();
            versionMetadataLocks.put(ga, lock);
        }
    }
    boolean locked = false;
    try {
        locked = lock.tryLock(kojiConfig.getLockTimeoutSeconds(), TimeUnit.SECONDS);
        if (!locked) {
            throw new IndyWorkflowException("Failed to acquire Koji GA version metadata lock on: %s in %d seconds.", ga, kojiConfig.getLockTimeoutSeconds());
        }
        Metadata metadata = versionMetadata.get(ga);
        ProjectRef ref = ga;
        if (metadata == null) {
            try {
                metadata = kojiClient.withKojiSession((session) -> {
                    // short-term caches to help improve performance a bit by avoiding xml-rpc calls.
                    Map<Integer, KojiBuildArchiveCollection> seenBuildArchives = new HashMap<>();
                    Set<Integer> seenBuilds = new HashSet<>();
                    List<KojiArchiveInfo> archives = kojiClient.listArchivesMatching(ref, session);
                    Set<SingleVersion> versions = new HashSet<>();
                    for (KojiArchiveInfo archive : archives) {
                        if (!archive.getFilename().endsWith(".pom")) {
                            logger.debug("Skipping non-POM: {}", archive.getFilename());
                            continue;
                        }
                        SingleVersion singleVersion = VersionUtils.createSingleVersion(archive.getVersion());
                        if (versions.contains(singleVersion)) {
                            logger.debug("Skipping already collected version: {}", archive.getVersion());
                            continue;
                        }
                        KojiBuildInfo build;
                        if (seenBuilds.contains(archive.getBuildId())) {
                            logger.debug("Skipping already seen build: {}", archive.getBuildId());
                            continue;
                        } else {
                            build = kojiClient.getBuildInfo(archive.getBuildId(), session);
                            seenBuilds.add(archive.getBuildId());
                        }
                        if (build == null) {
                            logger.debug("Cannot retrieve build info: {}. Skipping: {}", archive.getBuildId(), archive.getFilename());
                            continue;
                        }
                        if (build.getBuildState() != KojiBuildState.COMPLETE) {
                            logger.debug("Build: {} is not completed. The state is {}. Skipping.", build.getNvr(), build.getBuildState());
                            continue;
                        }
                        if (build.getTaskId() == null) {
                            logger.debug("Build: {} is not a real build. It looks like a binary import. Skipping.", build.getNvr());
                            // This is not a real build, it's a binary import.
                            continue;
                        }
                        boolean buildAllowed = false;
                        if (!kojiConfig.isTagPatternsEnabled()) {
                            buildAllowed = true;
                        } else {
                            logger.debug("Checking for builds/tags of: {}", archive);
                            List<KojiTagInfo> tags = kojiClient.listTags(build.getId(), session);
                            for (KojiTagInfo tag : tags) {
                                if (kojiConfig.isTagAllowed(tag.getName())) {
                                    logger.debug("Koji tag: {} is allowed for proxying.", tag.getName());
                                    buildAllowed = true;
                                    break;
                                } else {
                                    logger.debug("Koji tag: {} is not allowed for proxying.", tag.getName());
                                }
                            }
                        }
                        logger.debug("Checking if build passed tag whitelist check and doesn't collide with something in authority store (if configured)...");
                        if (buildAllowed && buildAuthority.isAuthorized(path, new EventMetadata(), ref, build, session, seenBuildArchives)) {
                            try {
                                logger.debug("Adding version: {} for: {}", archive.getVersion(), path);
                                versions.add(singleVersion);
                            } catch (InvalidVersionSpecificationException e) {
                                logger.warn(String.format("Encountered invalid version: %s for archive: %s. Reason: %s", archive.getVersion(), archive.getArchiveId(), e.getMessage()), e);
                            }
                        }
                    }
                    if (versions.isEmpty()) {
                        logger.debug("No versions found in Koji builds for metadata: {}", path);
                        return null;
                    }
                    List<SingleVersion> sortedVersions = new ArrayList<>(versions);
                    Collections.sort(sortedVersions);
                    Metadata md = new Metadata();
                    md.setGroupId(ref.getGroupId());
                    md.setArtifactId(ref.getArtifactId());
                    Versioning versioning = new Versioning();
                    versioning.setRelease(sortedVersions.get(versions.size() - 1).renderStandard());
                    versioning.setLatest(sortedVersions.get(versions.size() - 1).renderStandard());
                    versioning.setVersions(sortedVersions.stream().map(SingleVersion::renderStandard).collect(Collectors.toList()));
                    Date lastUpdated = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime();
                    versioning.setLastUpdated(new SimpleDateFormat(LAST_UPDATED_FORMAT).format(lastUpdated));
                    md.setVersioning(versioning);
                    return md;
                });
            } catch (KojiClientException e) {
                throw new IndyWorkflowException("Failed to retrieve version metadata for: %s from Koji. Reason: %s", e, ga, e.getMessage());
            }
            Metadata md = metadata;
            if (metadata != null) {
                // FIXME: Need a way to listen for cache expiration and re-request this?
                versionMetadata.execute((cache) -> cache.getAdvancedCache().put(ref, md, kojiConfig.getMetadataTimeoutSeconds(), TimeUnit.SECONDS));
            }
        }
        return metadata;
    } catch (InterruptedException e) {
        logger.warn("Interrupted waiting for Koji GA version metadata lock on target: {}", ga);
    } finally {
        if (locked) {
            lock.unlock();
        }
    }
    logger.debug("Returning null metadata result for unknown reason (path: '{}')", path);
    return null;
}
Also used : SingleVersion(org.commonjava.maven.atlas.ident.version.SingleVersion) Date(java.util.Date) SimpleProjectRef(org.commonjava.maven.atlas.ident.ref.SimpleProjectRef) LoggerFactory(org.slf4j.LoggerFactory) MavenMetadataProvider(org.commonjava.indy.pkg.maven.content.group.MavenMetadataProvider) SimpleDateFormat(java.text.SimpleDateFormat) HashMap(java.util.HashMap) KojiTagInfo(com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) HashSet(java.util.HashSet) VersionUtils(org.commonjava.maven.atlas.ident.util.VersionUtils) Calendar(java.util.Calendar) IndyWorkflowException(org.commonjava.indy.IndyWorkflowException) MetricNamed(org.commonjava.indy.measure.annotation.MetricNamed) ProjectRef(org.commonjava.maven.atlas.ident.ref.ProjectRef) Map(java.util.Map) KojiArchiveInfo(com.redhat.red.build.koji.model.xmlrpc.KojiArchiveInfo) KojiClientException(com.redhat.red.build.koji.KojiClientException) StoreKey(org.commonjava.indy.model.core.StoreKey) WeakHashMap(java.util.WeakHashMap) StoreType.group(org.commonjava.indy.model.core.StoreType.group) Versioning(org.apache.maven.artifact.repository.metadata.Versioning) Logger(org.slf4j.Logger) ReentrantLock(java.util.concurrent.locks.ReentrantLock) TimeZone(java.util.TimeZone) KojiClient(com.redhat.red.build.koji.KojiClient) IndyMetrics(org.commonjava.indy.measure.annotation.IndyMetrics) Set(java.util.Set) Collectors(java.util.stream.Collectors) CacheHandle(org.commonjava.indy.subsys.infinispan.CacheHandle) InvalidRefException(org.commonjava.maven.atlas.ident.ref.InvalidRefException) File(java.io.File) IndyMetricsKojiNames(org.commonjava.indy.koji.metrics.IndyMetricsKojiNames) TimeUnit(java.util.concurrent.TimeUnit) KojiBuildState(com.redhat.red.build.koji.model.xmlrpc.KojiBuildState) InvalidVersionSpecificationException(org.commonjava.maven.atlas.ident.version.InvalidVersionSpecificationException) List(java.util.List) KojiMavenVersionMetadataCache(org.commonjava.indy.koji.inject.KojiMavenVersionMetadataCache) Measure(org.commonjava.indy.measure.annotation.Measure) KojiBuildInfo(com.redhat.red.build.koji.model.xmlrpc.KojiBuildInfo) IndyMetricsNames(org.commonjava.indy.IndyMetricsNames) EventMetadata(org.commonjava.maven.galley.event.EventMetadata) Metadata(org.apache.maven.artifact.repository.metadata.Metadata) ApplicationScoped(javax.enterprise.context.ApplicationScoped) KojiBuildArchiveCollection(com.redhat.red.build.koji.model.xmlrpc.KojiBuildArchiveCollection) Collections(java.util.Collections) IndyKojiConfig(org.commonjava.indy.koji.conf.IndyKojiConfig) HashSet(java.util.HashSet) Set(java.util.Set) InvalidRefException(org.commonjava.maven.atlas.ident.ref.InvalidRefException) EventMetadata(org.commonjava.maven.galley.event.EventMetadata) Metadata(org.apache.maven.artifact.repository.metadata.Metadata) Logger(org.slf4j.Logger) KojiTagInfo(com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo) KojiArchiveInfo(com.redhat.red.build.koji.model.xmlrpc.KojiArchiveInfo) EventMetadata(org.commonjava.maven.galley.event.EventMetadata) IndyWorkflowException(org.commonjava.indy.IndyWorkflowException) ArrayList(java.util.ArrayList) List(java.util.List) SingleVersion(org.commonjava.maven.atlas.ident.version.SingleVersion) KojiBuildInfo(com.redhat.red.build.koji.model.xmlrpc.KojiBuildInfo) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Date(java.util.Date) SimpleProjectRef(org.commonjava.maven.atlas.ident.ref.SimpleProjectRef) Versioning(org.apache.maven.artifact.repository.metadata.Versioning) InvalidVersionSpecificationException(org.commonjava.maven.atlas.ident.version.InvalidVersionSpecificationException) KojiClientException(com.redhat.red.build.koji.KojiClientException) SimpleProjectRef(org.commonjava.maven.atlas.ident.ref.SimpleProjectRef) ProjectRef(org.commonjava.maven.atlas.ident.ref.ProjectRef) File(java.io.File) HashMap(java.util.HashMap) Map(java.util.Map) WeakHashMap(java.util.WeakHashMap) SimpleDateFormat(java.text.SimpleDateFormat) IndyMetrics(org.commonjava.indy.measure.annotation.IndyMetrics)

Example 2 with KojiTagInfo

use of com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo in project indy by Commonjava.

the class KojiContentManagerDecorator method proxyKojiBuild.

private <T> T proxyKojiBuild(final StoreKey inStore, final ArtifactRef artifactRef, final String path, EventMetadata eventMetadata, T defValue, KojiBuildAction<T> consumer) throws IndyWorkflowException {
    Logger logger = LoggerFactory.getLogger(getClass());
    try {
        return kojiClient.withKojiSession((session) -> {
            List<KojiBuildInfo> builds = kojiClient.listBuildsContaining(artifactRef, session);
            Collections.sort(builds, (build1, build2) -> build2.getCreationTime().compareTo(build1.getCreationTime()));
            logger.debug("Got {} builds from koji. Looking for best match.", builds.size());
            for (KojiBuildInfo build : builds) {
                if (build.getBuildState() != KojiBuildState.COMPLETE) {
                    logger.debug("Build: {} is not completed. The state is {}. Skipping.", build.getNvr(), build.getBuildState());
                    continue;
                }
                boolean buildAllowed = false;
                if (isBinaryBuild(build)) {
                    // This is not a real build, it's a binary import.
                    if (config.isProxyBinaryBuilds()) {
                        logger.info("Trying binary build: {} with id: {}", build.getNvr(), build.getId());
                        buildAllowed = true;
                    } else {
                        logger.debug("Skipping binary build: {} with id: {}", build.getNvr(), build.getId());
                    }
                } else {
                    logger.info("Trying build: {} with id: {}", build.getNvr(), build.getId());
                    if (!config.isTagPatternsEnabled()) {
                        buildAllowed = true;
                    } else {
                        List<KojiTagInfo> tags = kojiClient.listTags(build.getId(), session);
                        logger.debug("Build is in {} tags...", tags.size());
                        for (KojiTagInfo tag : tags) {
                            // If the tags match patterns configured in whitelist, construct a new remote repo.
                            if (config.isTagAllowed(tag.getName())) {
                                logger.info("Koji tag is on whitelist: {}", tag.getName());
                                buildAllowed = true;
                                break;
                            } else {
                                logger.debug("Tag: {} is not in the whitelist.", tag.getName());
                            }
                        }
                    }
                }
                if (buildAllowed) {
                    // or the artifact matches the one in the authoritative store, go ahead.
                    if (buildAuthority.isAuthorized(path, eventMetadata, artifactRef, build, session)) {
                        return consumer.execute(inStore, artifactRef, build, session);
                    }
                } else {
                    logger.debug("No whitelisted tags found for: {}", build.getNvr());
                }
            }
            logger.debug("No builds were found that matched the restrictions.");
            return defValue;
        });
    } catch (KojiClientException e) {
        throw new IndyWorkflowException("Cannot retrieve builds for: %s. Error: %s", e, artifactRef, e.getMessage());
    }
}
Also used : KojiClientException(com.redhat.red.build.koji.KojiClientException) IndyWorkflowException(org.commonjava.indy.IndyWorkflowException) Logger(org.slf4j.Logger) KojiTagInfo(com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo) KojiBuildInfo(com.redhat.red.build.koji.model.xmlrpc.KojiBuildInfo)

Aggregations

KojiClientException (com.redhat.red.build.koji.KojiClientException)2 KojiBuildInfo (com.redhat.red.build.koji.model.xmlrpc.KojiBuildInfo)2 KojiTagInfo (com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo)2 IndyWorkflowException (org.commonjava.indy.IndyWorkflowException)2 KojiClient (com.redhat.red.build.koji.KojiClient)1 KojiArchiveInfo (com.redhat.red.build.koji.model.xmlrpc.KojiArchiveInfo)1 KojiBuildArchiveCollection (com.redhat.red.build.koji.model.xmlrpc.KojiBuildArchiveCollection)1 KojiBuildState (com.redhat.red.build.koji.model.xmlrpc.KojiBuildState)1 File (java.io.File)1 SimpleDateFormat (java.text.SimpleDateFormat)1 ArrayList (java.util.ArrayList)1 Calendar (java.util.Calendar)1 Collections (java.util.Collections)1 Date (java.util.Date)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 TimeZone (java.util.TimeZone)1