Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registry client: option to cleanup old timestamped catalog artifacts #16327

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package io.quarkus.bootstrap.resolver.maven;

import io.quarkus.bootstrap.model.AppArtifactKey;
import io.quarkus.bootstrap.resolver.AppModelResolverException;
import io.quarkus.bootstrap.util.PropertyUtils;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand Down Expand Up @@ -208,7 +207,7 @@ public VersionRangeResult resolveVersionRange(Artifact artifact) throws Bootstra
}
}

public String getLatestVersionFromRange(Artifact artifact, String range) throws AppModelResolverException {
public String getLatestVersionFromRange(Artifact artifact, String range) throws BootstrapMavenException {
return getLatest(resolveVersionRange(new DefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(),
artifact.getClassifier(), artifact.getExtension(), range)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.registry.client.maven;

import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.devtools.messagewriter.MessageWriter;
import io.quarkus.maven.ArtifactCoords;
import io.quarkus.registry.RegistryResolutionException;
Expand All @@ -18,11 +17,11 @@ public class MavenNonPlatformExtensionsResolver
implements RegistryNonPlatformExtensionsResolver {

private final RegistryNonPlatformExtensionsConfig config;
private final MavenArtifactResolver artifactResolver;
private final MavenRegistryArtifactResolver artifactResolver;
private final MessageWriter log;

public MavenNonPlatformExtensionsResolver(RegistryNonPlatformExtensionsConfig config,
MavenArtifactResolver artifactResolver, MessageWriter log) {
MavenRegistryArtifactResolver artifactResolver, MessageWriter log) {
this.config = Objects.requireNonNull(config);
this.artifactResolver = Objects.requireNonNull(artifactResolver);
this.log = Objects.requireNonNull(log);
Expand All @@ -35,13 +34,15 @@ public ExtensionCatalog resolveNonPlatformExtensions(String quarkusVersion)
final Artifact catalogArtifact = new DefaultArtifact(baseCoords.getGroupId(),
baseCoords.getArtifactId(), quarkusVersion, baseCoords.getType(), baseCoords.getVersion());
log.debug("Resolving non-platform extension catalog %s", catalogArtifact);

final Path jsonFile;
try {
jsonFile = artifactResolver.resolve(catalogArtifact).getArtifact().getFile().toPath();
jsonFile = artifactResolver.resolve(catalogArtifact);
} catch (Exception e) {
log.debug("Failed to resolve non-platform extension catalog %s", catalogArtifact);
return null;
}

try {
return JsonCatalogMapperHelper.deserialize(jsonFile, JsonExtensionCatalog.class);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.registry.client.maven;

import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.devtools.messagewriter.MessageWriter;
import io.quarkus.maven.ArtifactCoords;
import io.quarkus.registry.RegistryResolutionException;
Expand All @@ -17,10 +16,10 @@

public class MavenPlatformExtensionsResolver implements RegistryPlatformExtensionsResolver {

private final MavenArtifactResolver artifactResolver;
private final MavenRegistryArtifactResolver artifactResolver;
private final MessageWriter log;

public MavenPlatformExtensionsResolver(MavenArtifactResolver artifactResolver,
public MavenPlatformExtensionsResolver(MavenRegistryArtifactResolver artifactResolver,
MessageWriter log) {
this.artifactResolver = Objects.requireNonNull(artifactResolver);
this.log = Objects.requireNonNull(log);
Expand All @@ -43,7 +42,7 @@ public ExtensionCatalog resolvePlatformExtensions(ArtifactCoords platformCoords)
log.debug("Resolving platform extension catalog %s", catalogArtifact);
final Path jsonPath;
try {
jsonPath = artifactResolver.resolve(catalogArtifact).getArtifact().getFile().toPath();
jsonPath = artifactResolver.resolve(catalogArtifact);
} catch (Exception e) {
throw new RegistryResolutionException("Failed to resolve Quarkus extensions catalog " + catalogArtifact,
e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.registry.client.maven;

import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.devtools.messagewriter.MessageWriter;
import io.quarkus.maven.ArtifactCoords;
import io.quarkus.registry.RegistryResolutionException;
Expand All @@ -18,10 +17,10 @@
public class MavenPlatformsResolver implements RegistryPlatformsResolver {

private final RegistryPlatformsConfig config;
private final MavenArtifactResolver artifactResolver;
private final MavenRegistryArtifactResolver artifactResolver;
private final MessageWriter log;

public MavenPlatformsResolver(RegistryPlatformsConfig config, MavenArtifactResolver artifactResolver,
public MavenPlatformsResolver(RegistryPlatformsConfig config, MavenRegistryArtifactResolver artifactResolver,
MessageWriter log) {
this.config = Objects.requireNonNull(config);
this.artifactResolver = Objects.requireNonNull(artifactResolver);
Expand All @@ -36,7 +35,7 @@ public PlatformCatalog resolvePlatforms(String quarkusVersion) throws RegistryRe
log.debug("Resolving platform catalog %s", catalogArtifact);
final Path jsonFile;
try {
jsonFile = artifactResolver.resolve(catalogArtifact).getArtifact().getFile().toPath();
jsonFile = artifactResolver.resolve(catalogArtifact);
} catch (Exception e) {
log.debug("Failed to resolve platform catalog %s", catalogArtifact);
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.registry.client.maven;

import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
import java.nio.file.Path;
import org.eclipse.aether.artifact.Artifact;

public interface MavenRegistryArtifactResolver {

Path resolve(Artifact artifact) throws BootstrapMavenException;

String getLatestVersionFromRange(Artifact artifact, String versionRange) throws BootstrapMavenException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.registry.client.maven;

import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.resolution.ArtifactResult;

public class MavenRegistryArtifactResolverWithCleanup implements MavenRegistryArtifactResolver {

private final MavenArtifactResolver resolver;
private final boolean cleanupTimestampedVersions;

public MavenRegistryArtifactResolverWithCleanup(MavenArtifactResolver resolver, boolean cleanupOldTimestampedVersions) {
this.resolver = Objects.requireNonNull(resolver, "resolver can't be null");
this.cleanupTimestampedVersions = cleanupOldTimestampedVersions;
}

@Override
public Path resolve(Artifact artifact) throws BootstrapMavenException {
return resolveAndCleanupOldTimestampedVersions(resolver, artifact, cleanupTimestampedVersions).getArtifact().getFile()
.toPath();
}

@Override
public String getLatestVersionFromRange(Artifact artifact, String versionRange) throws BootstrapMavenException {
return resolver.getLatestVersionFromRange(artifact, versionRange);
}

/**
* This method resolves an artifact and then will attempt to remove old timestamped SNAPSHOT versions.
*
* <p>
* IMPORTANT: it does not remove all the timestamped SNAPSHOT versions because otherwise, the artifacts
* will always be resolved from a remote repository even if the update policy does not require that.
*
* @param resolver Maven artifact resolver
* @param artifact artifact to resolve
* @param cleanupOldTimestampedVersions whether to remove old timestamped SNAPSHOT versions
* @return artifact resolution result
* @throws BootstrapMavenException in case the artifact could not be resolved
*/
protected static ArtifactResult resolveAndCleanupOldTimestampedVersions(MavenArtifactResolver resolver, Artifact artifact,
boolean cleanupOldTimestampedVersions) throws BootstrapMavenException {
if (!cleanupOldTimestampedVersions) {
return resolver.resolve(artifact);
}

final LocalRepositoryManager localRepoManager = resolver.getSession().getLocalRepositoryManager();
final File jsonDir = new File(localRepoManager.getRepository().getBasedir(),
localRepoManager.getPathForLocalArtifact(artifact)).getParentFile();
final List<String> existingFiles = jsonDir.exists() ? Arrays.asList(jsonDir.list()) : Collections.emptyList();

final ArtifactResult result = resolver.resolve(artifact);

final File[] jsonDirContent = jsonDir.listFiles();
if (jsonDirContent.length > existingFiles.size()) {
final String fileName = result.getArtifact().getFile().getName();
for (File c : jsonDirContent) {
if (c.getName().length() > fileName.length() && c.getName().startsWith(artifact.getArtifactId())
&& existingFiles.contains(c.getName())) {
c.deleteOnExit();
}
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

public class MavenRegistryClientFactory implements RegistryClientFactory {

private static final String CLEANUP_TIMESTAMPED_ARTIFACTS = "cleanup-timestamped-artifacts";

private MessageWriter log;
private MavenArtifactResolver originalResolver;
private List<RemoteRepository> singleRegistryRepos = new ArrayList<RemoteRepository>();
Expand Down Expand Up @@ -71,13 +73,16 @@ public RegistryClient buildRegistryClient(RegistryConfig config) throws Registry
resolver = newResolver(resolver, aggregatedRepos);
}

final boolean cleanupTimestampedArtifacts = isCleanupTimestampedArtifacts(config);

final ArtifactCoords originalDescrCoords = descriptorConfig.getArtifact();
final Artifact registryDescriptorCoords = new DefaultArtifact(originalDescrCoords.getGroupId(),
originalDescrCoords.getArtifactId(), originalDescrCoords.getClassifier(), originalDescrCoords.getType(),
originalDescrCoords.getVersion());
ArtifactResult result;
try {
result = resolver.resolve(registryDescriptorCoords);
result = MavenRegistryArtifactResolverWithCleanup.resolveAndCleanupOldTimestampedVersions(resolver,
registryDescriptorCoords, cleanupTimestampedArtifacts);
} catch (BootstrapMavenException e) {
final StringWriter buf = new StringWriter();
try (BufferedWriter writer = new BufferedWriter(buf)) {
Expand Down Expand Up @@ -133,14 +138,15 @@ public RegistryClient buildRegistryClient(RegistryConfig config) throws Registry
config = complete;
}

MavenRegistryArtifactResolver defaultResolver = null;
final RegistryNonPlatformExtensionsResolver nonPlatformExtensionsResolver;
final RegistryNonPlatformExtensionsConfig nonPlatformExtensions = config.getNonPlatformExtensions();
if (nonPlatformExtensions == null || nonPlatformExtensions.isDisabled()) {
log.debug("Non-platform extension catalogs were disabled for registry %s", config.getId());
nonPlatformExtensionsResolver = null;
} else {
nonPlatformExtensionsResolver = new MavenNonPlatformExtensionsResolver(nonPlatformExtensions,
resolver, log);
defaultResolver = defaultResolver(resolver, cleanupTimestampedArtifacts), log);
}

final RegistryPlatformsResolver platformsResolver;
Expand All @@ -149,16 +155,33 @@ public RegistryClient buildRegistryClient(RegistryConfig config) throws Registry
log.debug("Platform catalogs were disabled for registry %s", config.getId());
platformsResolver = null;
} else {
platformsResolver = new MavenPlatformsResolver(platformsConfig, resolver, log);
platformsResolver = new MavenPlatformsResolver(platformsConfig,
defaultResolver == null ? defaultResolver = defaultResolver(resolver, cleanupTimestampedArtifacts)
: defaultResolver,
log);
}

return new RegistryClientDispatcher(config, platformsResolver,
Boolean.TRUE.equals(config.getPlatforms().getExtensionCatalogsIncluded())
? new MavenPlatformExtensionsResolver(resolver, log)
: new MavenPlatformExtensionsResolver(originalResolver, log),
? new MavenPlatformExtensionsResolver(
defaultResolver == null ? defaultResolver(resolver, cleanupTimestampedArtifacts)
: defaultResolver,
log)
: new MavenPlatformExtensionsResolver(defaultResolver(originalResolver, cleanupTimestampedArtifacts),
log),
nonPlatformExtensionsResolver);
}

private static boolean isCleanupTimestampedArtifacts(RegistryConfig config) {
final Object o = config.getExtra().get(CLEANUP_TIMESTAMPED_ARTIFACTS);
return o == null ? true : Boolean.parseBoolean(o.toString());
}

private static MavenRegistryArtifactResolver defaultResolver(MavenArtifactResolver resolver,
boolean cleanupTimestampedArtifacts) {
return new MavenRegistryArtifactResolverWithCleanup(resolver, cleanupTimestampedArtifacts);
}

private static void complete(JsonRegistryConfig complete, RegistryConfig original, RegistryConfig descriptor) {
complete.setId(original.getId() == null ? descriptor.getId() : original.getId());

Expand Down