Skip to content

Commit

Permalink
[Issue-759] If available, channel changes replace component updates in
Browse files Browse the repository at this point in the history
update lists
  • Loading branch information
parsharma authored and spyrkob committed Nov 1, 2024
1 parent e5bccc8 commit edb12db
Show file tree
Hide file tree
Showing 14 changed files with 899 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.wildfly.prospero.it.commonapi;

import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.artifact.Artifact;
Expand All @@ -36,6 +37,7 @@
import org.wildfly.channel.Stream;
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.api.exceptions.MetadataException;
import org.wildfly.prospero.api.exceptions.OperationException;
import org.wildfly.prospero.metadata.ManifestVersionRecord;
import org.wildfly.prospero.actions.UpdateAction;
import org.wildfly.prospero.api.MavenOptions;
Expand Down Expand Up @@ -78,6 +80,9 @@ public class UpdateTest extends WfCoreTestBase {
public void setUp() throws Exception {
super.setUp();
mockRepo = temp.newFolder("repo");

// remove cached manifests between tests
FileUtils.deleteQuietly(localCachePath.resolve(Path.of("test", "channel")).toFile());
}

@After
Expand Down Expand Up @@ -252,6 +257,43 @@ public void candidateFolderHasToBeEmpty() throws Exception {
.message().contains("Can't install the server into a non empty directory");
}

@Test
public void rejectUpdateWhenManifestDowngradeIsDetected() throws Exception {
// deploy manifest file
File manifestFile = new File(MetadataTestUtils.class.getClassLoader().getResource(CHANNEL_BASE_CORE_19).toURI());
deployManifestFile(mockRepo.toURI().toURL(), manifestFile, "1.0.1");

// provision using channel gav
final ProvisioningDefinition provisioningDefinition = defaultWfCoreDefinition()
.setChannelCoordinates(buildConfigWithMockRepo().toPath().toString())
.setOverrideRepositories(Collections.emptyList()) // reset overrides from defaultWfCoreDefinition()
.build();
installation.provision(provisioningDefinition.toProvisioningConfig(),
provisioningDefinition.resolveChannels(CHANNELS_RESOLVER_FACTORY));

Optional<Artifact> wildflyCliArtifact = readArtifactFromManifest("org.wildfly.core", "wildfly-cli");
assertEquals(BASE_VERSION, wildflyCliArtifact.get().getVersion());

// delete the metadata file, so that the lower version of manifest can be resolved in an update
final Path manifestMetadata = mockRepo.toPath().resolve(Path.of("test", "channel", "maven-metadata.xml"));
Files.delete(manifestMetadata);

// update manifest file
final File updatedManifest = upgradeTestArtifactIn(manifestFile);
deployManifestFile(mockRepo.toURI().toURL(), updatedManifest, "1.0.0");


// update installation
Assertions.assertThatThrownBy(()->
new UpdateAction(outputPath, mavenOptions, new AcceptingConsole(), Collections.emptyList())
.performUpdate())
.isInstanceOf(OperationException.class)
.hasMessageContaining("PRSP000276: Unable to perform the update");

wildflyCliArtifact = readArtifactFromManifest("org.wildfly.core", "wildfly-cli");
assertEquals(BASE_VERSION, wildflyCliArtifact.get().getVersion());
}

private File upgradeTestArtifactIn(File manifestFile) throws IOException, MetadataException {
final ChannelManifest manifest = ManifestYamlSupport.parse(manifestFile);
final List<Stream> streams = manifest.getStreams().stream().map(s -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public class WfCoreTestBase {

protected static Artifact resolvedUpgradeArtifact;
protected static Artifact resolvedUpgradeClientArtifact;
private static Path localCachePath;
protected static Path localCachePath;
protected Path outputPath;
protected Path manifestPath;
protected ProvisioningAction installation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;
import org.wildfly.prospero.api.ChannelVersionChange;
import org.wildfly.prospero.api.Console;
import org.wildfly.prospero.api.ProvisioningProgressEvent;
import org.wildfly.prospero.api.ArtifactChange;
Expand Down Expand Up @@ -174,6 +175,18 @@ public void updatesFound(List<ArtifactChange> artifactUpdates) {
}
}

public void manifestUpdate(List<ChannelVersionChange> manifestChanges) {
if (manifestChanges.isEmpty()) {
println(CliMessages.MESSAGES.unableToChannelVersions());
} else {
println("");
println(CliMessages.MESSAGES.updatededChannelVersionsHeader());
for (ChannelVersionChange change : manifestChanges) {
println(change.shortDescription());
}
}
}

public void printArtifactChanges(List<ArtifactChange> artifactUpdates) {
if (!artifactUpdates.isEmpty()) {
getStdOut().println(CliMessages.MESSAGES.changesFound());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Set;

import static java.lang.String.format;
import static org.wildfly.prospero.cli.commands.CliConstants.VERBOSE;

public interface CliMessages {

Expand Down Expand Up @@ -726,4 +727,16 @@ default OperationException cancelledByConfilcts() {
default String downgradeDetected(){
return bundle.getString("prospero.perform.update.downgrade.detected");
}

default String fullUpdatesOption(String paramName) {
return String.format(bundle.getString("prospero.updates.full_list_option"), VERBOSE);
}

default String unableToChannelVersions() {
return bundle.getString("prospero.updates.channel_versions_unknown");
}

default String updatededChannelVersionsHeader() {
return bundle.getString("prospero.updates.channel_updates_header");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.wildfly.prospero.cli.commands;

import static org.wildfly.prospero.cli.commands.CliConstants.VERBOSE;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
Expand All @@ -29,7 +31,6 @@
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
import org.eclipse.aether.artifact.Artifact;
import org.jboss.galleon.ProvisioningException;
import org.jboss.galleon.diff.FsDiff;
import org.jboss.galleon.diff.FsEntry;
Expand All @@ -40,7 +41,6 @@
import org.wildfly.channel.ChannelManifest;
import org.wildfly.channel.ChannelManifestCoordinate;
import org.wildfly.channel.Repository;
import org.wildfly.channel.version.VersionMatcher;
import org.wildfly.prospero.ProsperoLogger;
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.actions.SubscribeNewServerAction;
Expand All @@ -62,7 +62,6 @@
import org.wildfly.prospero.api.TemporaryFilesManager;
import org.wildfly.prospero.galleon.FeaturePackLocationParser;
import org.wildfly.prospero.galleon.GalleonUtils;
import org.wildfly.prospero.metadata.ManifestVersionRecord;
import org.wildfly.prospero.metadata.ProsperoMetadataUtils;
import org.wildfly.prospero.model.InstallationProfile;
import org.wildfly.prospero.updates.UpdateSet;
Expand Down Expand Up @@ -123,6 +122,7 @@ public Integer call() throws Exception {
log.tracef("Perform full update");

console.println(CliMessages.MESSAGES.updateHeader(installationDir));

try (UpdateAction updateAction = actionFactory.update(installationDir, mavenOptions, console, repositories)) {
performUpdate(updateAction, yes, console, installationDir, noConflictsOnly);
}
Expand All @@ -138,18 +138,8 @@ private boolean performUpdate(UpdateAction updateAction, boolean yes, CliConsole
Path targetDir = null;
try {
targetDir = Files.createTempDirectory("update-candidate");
try (InstallationMetadata installationMetadata = updateAction.getInstallationMetadata()) {
if (installationMetadata.getManifestVersions().isPresent()) {
List<ManifestVersionRecord.MavenManifest> mavenManifests = installationMetadata.getManifestVersions().get().getMavenManifests();
final List<Artifact> manifestUpdates = updateAction.findCurrentChannelSessionManifests();
if (!isManifestDowngraded(mavenManifests, manifestUpdates)) {
console.println(CliMessages.MESSAGES.downgradeDetected());
return false; // Terminate the method if a downgrade is detected
}
}
}

if (buildUpdate(updateAction, targetDir, yes, console, () -> console.confirmUpdates())) {
if (buildUpdate(updateAction, targetDir, yes, console, () -> console.confirmUpdates(), verbose)) {
console.println("");
console.buildUpdatesComplete();

Expand Down Expand Up @@ -217,7 +207,7 @@ public Integer call() throws Exception {

try (UpdateAction updateAction = actionFactory.update(installationDir,
mavenOptions, console, repositories)) {
if (buildUpdate(updateAction, candidateDirectory, yes, console, () -> console.confirmBuildUpdates())) {
if (buildUpdate(updateAction, candidateDirectory, yes, console, () -> console.confirmBuildUpdates(), verbose)) {
console.println("");
console.buildUpdatesComplete();
console.println(CliMessages.MESSAGES.updateCandidateGenerated(candidateDirectory));
Expand Down Expand Up @@ -280,7 +270,9 @@ public Integer call() throws Exception {
throw CliMessages.MESSAGES.notCandidate(candidateDir.toAbsolutePath());
}

console.updatesFound(applyCandidateAction.findUpdates().getArtifactUpdates());
final UpdateSet updates = applyCandidateAction.findUpdates();
printUpdates(console, updates, verbose);

final List<FileConflict> conflicts = applyCandidateAction.getConflicts();
FileConflictPrinter.print(conflicts, console);

Expand Down Expand Up @@ -329,8 +321,8 @@ public Integer call() throws Exception {
RepositoryDefinition.from(temporaryRepositories), temporaryFiles);
console.println(CliMessages.MESSAGES.checkUpdatesHeader(installationDir));
try (UpdateAction updateAction = actionFactory.update(installationDir, mavenOptions, console, repositories)) {
final UpdateSet updateSet = updateAction.findUpdates();
console.updatesFound(updateSet.getArtifactUpdates());
final UpdateSet updates = updateAction.findUpdates();
printUpdates(console, updates, verbose);
}

final float totalTime = (System.currentTimeMillis() - startTime) / 1000f;
Expand Down Expand Up @@ -466,9 +458,12 @@ public UpdateCommand(CliConsole console, ActionFactory actionFactory) {

}

private static boolean buildUpdate(UpdateAction updateAction, Path updateDirectory, boolean yes, CliConsole console, Supplier<Boolean> confirmation) throws OperationException, ProvisioningException {
private static boolean buildUpdate(UpdateAction updateAction, Path updateDirectory,
boolean yes, CliConsole console, Supplier<Boolean> confirmation,
boolean verbose) throws OperationException, ProvisioningException {
final UpdateSet updateSet = updateAction.findUpdates();
console.updatesFound(updateSet.getArtifactUpdates());
printUpdates(console, updateSet, verbose);

if (updateSet.isEmpty()) {
return false;
}
Expand All @@ -482,6 +477,26 @@ private static boolean buildUpdate(UpdateAction updateAction, Path updateDirecto
return true;
}

private static void printUpdates(CliConsole console, UpdateSet updates, boolean verbose) throws OperationException {
if (updates.hasManifestDowngrade()) {
final String summary = String.join(";", updates.getManifestDowngradeDescriptions());
throw ProsperoLogger.ROOT_LOGGER.manifestDowngrade(summary);
}

// only print the full list of components if asked for or if the manifests versions are not complete
if (!updates.isAuthoritativeManifestVersions() || verbose) {
if (!updates.getManifestChanges().isEmpty()) {
console.manifestUpdate(updates.getManifestChanges());
console.println("");
}
console.updatesFound(updates.getArtifactUpdates());
} else {
console.manifestUpdate(updates.getManifestChanges());
console.println("");
console.println(CliMessages.MESSAGES.fullUpdatesOption(VERBOSE));
}
}

public static void verifyInstallationContainsOnlyProspero(Path dir) throws ArgumentParsingException {
verifyDirectoryContainsInstallation(dir);

Expand All @@ -506,37 +521,4 @@ public static Path detectProsperoInstallationPath() throws ArgumentParsingExcept
return Paths.get(modulePath).toAbsolutePath().getParent();
}


public static boolean isManifestDowngraded(List<ManifestVersionRecord.MavenManifest> mavenManifests, List<Artifact> manifestUpdates ) {

for (ManifestVersionRecord.MavenManifest installedManifest : mavenManifests) {
Artifact updateArtifact = null;

// Find the corresponding update artifact for the installedManifest
for (Artifact manifestUpdate : manifestUpdates) {
if (manifestUpdate.getGroupId().equals(installedManifest.getGroupId()) &&
manifestUpdate.getArtifactId().equals(installedManifest.getArtifactId())) {
updateArtifact = manifestUpdate;
break;
}
}

if (updateArtifact != null) {
// Compare versions
String installedVersion = installedManifest.getVersion();
String availableVersion = updateArtifact.getVersion();
if (VersionMatcher.COMPARATOR.compare(installedVersion, availableVersion) < 0) {
log.debugf("Upgrade available for %s:%s: %s -> %s",
installedManifest.getGroupId(), installedManifest.getArtifactId(), installedVersion, availableVersion);
return true;
} else if (VersionMatcher.COMPARATOR.compare(installedVersion, availableVersion) > 0) {
log.debugf("Downgrade detected for " + installedManifest.getArtifactId() + ": " + installedVersion + " -> " + availableVersion);
return false;
} else {
System.out.println(installedManifest.getArtifactId() + " is up to date.");
}
}
}
return true;
}
}
4 changes: 4 additions & 0 deletions prospero-cli/src/main/resources/UsageMessages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ prospero.update.subscribe.conflict.prompt.continue=Copy metadata files.
prospero.update.subscribe.conflict.prompt.cancel=Quit without generating metadata files.
prospero.update.subscribe.meta.exists=Path `%s` contains a server installation provisioned by the %s already.

prospero.updates.full_list_option=To see the full list of component changes, use `%s` option.
prospero.updates.channel_versions_unknown=Unable to discover updated channel versions. Displaying updated components.
prospero.updates.channel_updates_header=Updates summary

prospero.history.no_updates=No changes found
prospero.history.feature_pack.title=Feature Pack
prospero.history.configuration_model.title=configuration model
Expand Down
Loading

0 comments on commit edb12db

Please sign in to comment.