diff --git a/.github/release/maven-settings.xml.gpg b/.github/release/maven-settings.xml.gpg
new file mode 100644
index 000000000..3bf3100ef
Binary files /dev/null and b/.github/release/maven-settings.xml.gpg differ
diff --git a/.github/workflows/future.yml b/.github/workflows/future.yml
deleted file mode 100644
index 0aaf939f0..000000000
--- a/.github/workflows/future.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: Build
-
-on:
- pull_request:
- branches:
- - 'future'
- paths-ignore:
- - '.gitignore'
- - 'examples'
- - 'README.md'
-
-jobs:
- build:
- name: ${{ matrix.os }}-${{ matrix.jdk }}
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- os: [ ubuntu-latest, windows-latest ]
- jdk: [ 11, 17, 21 ]
- steps:
- - uses: actions/checkout@v2
- with:
- fetch-depth: 0
- - uses: actions/cache@v1
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven-
- - name: Set up JDK ${{ matrix.jdk }}
- uses: actions/setup-java@v2
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'adopt'
- cache: maven
- - name: Build and test
- run: mvn clean install -DallTests -Pdist
- - uses: actions/upload-artifact@v2
- if: failure()
- with:
- name: surefire-reports
- path: '**/surefire-reports/*.txt'
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 26785ace6..5fb48c5f3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -3,7 +3,7 @@ name: Build
on:
push:
branches:
- - main
+ - 1.3.x
paths-ignore:
- '.gitignore'
- 'examples'
@@ -24,7 +24,7 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
- jdk: [ 11, 17, 21 ]
+ jdk: [ 17, 21 ]
steps:
- uses: actions/checkout@v2
with:
@@ -40,7 +40,7 @@ jobs:
- uses: actions/upload-artifact@v4
if: failure()
with:
- name: surefire-reports
+ name: surefire-reports-${{ matrix.os }}-${{ matrix.jdk }}
path: '**/surefire-reports/*.txt'
pmd:
name: ubuntu-latest-pmd
@@ -52,7 +52,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v2
with:
- java-version: 11
+ java-version: 17
distribution: 'adopt'
cache: maven
- name: Build and test
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 68cf8c7d2..0727451e3 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -21,15 +21,23 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
- java-version: 11
+ java-version: 17
- name: maven release ${{steps.metadata.outputs.current-version}}
run: |
java -version
+ gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.SECRET_PASSPHRASE }}" --output maven-settings.xml .github/release/maven-settings.xml.gpg
git config --global user.name "WildFly Prospero CI"
git config --global user.email "wildfly-dev@lists.jboss.org"
git checkout -b release
- mvn -B release:prepare -Pdist,jboss-release -DreleaseVersion=${{steps.metadata.outputs.current-version}} -DdevelopmentVersion=${{steps.metadata.outputs.next-version}}
+ mvn -B release:prepare -Pdist,jboss-release -DreleaseVersion=${{steps.metadata.outputs.current-version}} -DdevelopmentVersion=${{steps.metadata.outputs.next-version}} -s maven-settings.xml
git checkout ${{github.base_ref}}
git rebase release
+ mvn -B release:perform -Pdist,jboss-release -s maven-settings.xml
git push
git push --tags
+ - name: Create GH release
+ uses: softprops/action-gh-release@v2
+ with:
+ files: dist/build/target/prospero-${{steps.metadata.outputs.current-version}}.zip
+ tag_name: ${{steps.metadata.outputs.current-version}}
+ prerelease: contains(${{steps.metadata.outputs.current-version}}, "Beta")
diff --git a/integration-tests/src/test/java/org/wildfly/prospero/it/cli/CacheManifestTest.java b/integration-tests/src/test/java/org/wildfly/prospero/it/cli/CacheManifestTest.java
index cc89893d8..3d75c6d7a 100644
--- a/integration-tests/src/test/java/org/wildfly/prospero/it/cli/CacheManifestTest.java
+++ b/integration-tests/src/test/java/org/wildfly/prospero/it/cli/CacheManifestTest.java
@@ -102,8 +102,10 @@ public void setUp() throws Exception {
));
// create and deploy second manifest
- secondManifest = new ChannelManifest(null, null, null, null,
- List.of(new Stream("org.wildfly.core", "wildfly-controller", UPGRADE_VERSION)));
+ secondManifest = new ChannelManifest.Builder()
+ .setSchemaVersion("1.0.0")
+ .addStreams(new Stream("org.wildfly.core", "wildfly-controller", UPGRADE_VERSION))
+ .build();
repositoryUtils.deployArtifact(new DefaultArtifact(
"org.test.channels",
"wf-core-second",
@@ -321,7 +323,7 @@ public void updateWithManifestNotInCacheAndNotAvailableFails() throws Exception
assertThatThrownBy(()->performUpdate())
.isInstanceOf(UnresolvedChannelMetadataException.class)
.hasFieldOrPropertyWithValue("missingArtifacts",
- Set.of(new ChannelMetadataCoordinate("org.test.channels", "wf-core-base", "",
+ Set.of(new ChannelMetadataCoordinate("org.test.channels", "wf-core-base", "1.0.0",
ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION)));
}
@@ -383,6 +385,7 @@ private ChannelManifest updateWildflyController() throws MalformedURLException {
return new ChannelManifest(
sourceManifest.getSchemaVersion(),
sourceManifest.getId(),
+ sourceManifest.getLogicalVersion(),
sourceManifest.getDescription(),
sourceManifest.getManifestRequirements(),
streams);
diff --git a/pom.xml b/pom.xml
index ed0a5f332..ba939cc5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,24 +39,24 @@
prospero-standalone-galleon-pack
${project.groupId}
- 2.3.17.Final
+ 2.3.18.Final
1.17.1
2.17.0
- 3.0.0
+ 3.1.1
1.12.0
4.5.14
4.4.16
3.1.0
3.0.2
- 3.25.0
- 3.8.0
- 1.9.21
+ 3.26.0
+ 3.8.1
+ 1.9.22
3.6.3
2.1.1
1.27
3.5.0
1.5.0.Final
- 6.0.3.Final
+ 6.0.4.Final
6.9.0.202403050737-r
2.17.0
2.1.19.Final
@@ -65,18 +65,18 @@
2.1.5.Final
3.8.16.Final
1.7.0.Final
- 7.2.0.Final
- 1.0.3.Final
- 2.4.1.Final
- 1.2.1.Final
- 5.14.1
+ 7.3.0.Final
+ 2.0.0.Beta1
+ 2.4.2.Final
+ 1.3.0.Beta2
+ 5.14.2
2.0.7
2.2
4.13.2
3.6.0
- 1.1.0.Final
+ 1.2.1.Final
3.10.1
- 33.0.2.Final
+ 34.0.0.Final
4.7.6
1.19.0
3.26.3
@@ -518,10 +518,10 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 11
- 11
- 11
+
+ 17
+ 17
+ 17
@@ -565,6 +565,8 @@
@{project.version}
clean install
+ true
+ false
diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java
index 11684f402..daaf29292 100644
--- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java
+++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java
@@ -716,4 +716,10 @@ default String candidateApplyRollbackSuccess() {
default String candidateApplyRollbackFailure(Path backup) {
return format(bundle.getString("prospero.candidate.apply.error.rollback_error.desc"), backup);
}
+
+ default OperationException cancelledByConfilcts() {
+ return new OperationException(format(
+ bundle.getString("prospero.updates.apply.candidate.cancel_conflicts"),
+ CliConstants.NO_CONFLICTS_ONLY));
+ }
}
diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java
index 6fa3b30e4..67baaaf89 100644
--- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java
+++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java
@@ -101,4 +101,7 @@ private Commands() {
public static final String VV = "-vv";
public static final String Y = "-y";
public static final String YES = "--yes";
+ public static final String NO_CONFLICTS_ONLY = "--no-conflicts-only";
+ public static final String DRY_RUN = "--dry-run";
+
}
diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/RevertCommand.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/RevertCommand.java
index b86b8f95a..3116ccb70 100644
--- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/RevertCommand.java
+++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/RevertCommand.java
@@ -52,12 +52,22 @@
)
public class RevertCommand extends AbstractParentCommand {
- private static int applyCandidate(CliConsole console, ApplyCandidateAction applyCandidateAction, boolean yes) throws OperationException, ProvisioningException {
+ private static int applyCandidate(CliConsole console, ApplyCandidateAction applyCandidateAction,
+ boolean yes, boolean noConflictsOnly, boolean dryRun)
+ throws OperationException, ProvisioningException {
List artifactUpdates = applyCandidateAction.findUpdates().getArtifactUpdates();
console.printArtifactChanges(artifactUpdates);
final List conflicts = applyCandidateAction.getConflicts();
FileConflictPrinter.print(conflicts, console);
+ if (dryRun) {
+ return SUCCESS;
+ }
+
+ if (noConflictsOnly && !conflicts.isEmpty()) {
+ throw CliMessages.MESSAGES.cancelledByConfilcts();
+ }
+
if (!yes && !artifactUpdates.isEmpty() && !console.confirm(CliMessages.MESSAGES.continueWithRevert(),
CliMessages.MESSAGES.applyingChanges(), CliMessages.MESSAGES.revertCancelled())) {
return SUCCESS;
@@ -92,6 +102,9 @@ public static class PerformCommand extends AbstractMavenCommand {
@CommandLine.Option(names = {CliConstants.Y, CliConstants.YES})
boolean yes;
+ @CommandLine.Option(names = {CliConstants.NO_CONFLICTS_ONLY})
+ boolean noConflictsOnly;
+
public PerformCommand(CliConsole console, ActionFactory actionFactory) {
super(console, actionFactory);
}
@@ -121,7 +134,7 @@ public Integer call() throws Exception {
validateRevertCandidate(installationDirectory, tempDirectory, applyCandidateAction);
- applyCandidate(console, applyCandidateAction, yes);
+ applyCandidate(console, applyCandidateAction, yes, noConflictsOnly, false);
} catch (IOException e) {
throw ProsperoLogger.ROOT_LOGGER.unableToCreateTemporaryDirectory(e);
}
@@ -147,6 +160,12 @@ public static class ApplyCommand extends AbstractCommand {
@CommandLine.Option(names = {CliConstants.Y, CliConstants.YES})
boolean yes;
+ @CommandLine.Option(names = {CliConstants.NO_CONFLICTS_ONLY})
+ boolean noConflictsOnly;
+
+ @CommandLine.Option(names = {CliConstants.DRY_RUN})
+ boolean dryRun;
+
public ApplyCommand(CliConsole console, ActionFactory actionFactory) {
super(console, actionFactory);
}
@@ -162,7 +181,7 @@ public Integer call() throws Exception {
console.println(CliMessages.MESSAGES.revertStart(installationDirectory, applyCandidateAction.getCandidateRevision().getName()));
console.println("");
- applyCandidate(console, applyCandidateAction, yes);
+ applyCandidate(console, applyCandidateAction, yes, noConflictsOnly, dryRun);
if(remove) {
applyCandidateAction.removeCandidate(candidateDirectory.toFile());
}
diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/UpdateCommand.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/UpdateCommand.java
index d1cdc898e..675181a3a 100644
--- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/UpdateCommand.java
+++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/UpdateCommand.java
@@ -89,6 +89,9 @@ public static class PerformCommand extends AbstractMavenCommand {
@CommandLine.Option(names = {CliConstants.Y, CliConstants.YES})
boolean yes;
+ @CommandLine.Option(names = {CliConstants.NO_CONFLICTS_ONLY})
+ boolean noConflictsOnly;
+
public PerformCommand(CliConsole console, ActionFactory actionFactory) {
super(console, actionFactory);
}
@@ -119,7 +122,7 @@ public Integer call() throws Exception {
console.println(CliMessages.MESSAGES.updateHeader(installationDir));
try (UpdateAction updateAction = actionFactory.update(installationDir, mavenOptions, console, repositories)) {
- performUpdate(updateAction, yes, console, installationDir);
+ performUpdate(updateAction, yes, console, installationDir, noConflictsOnly);
}
}
@@ -129,7 +132,7 @@ public Integer call() throws Exception {
return ReturnCodes.SUCCESS;
}
- private boolean performUpdate(UpdateAction updateAction, boolean yes, CliConsole console, Path installDir) throws OperationException, ProvisioningException {
+ private boolean performUpdate(UpdateAction updateAction, boolean yes, CliConsole console, Path installDir, boolean noConflictsOnly) throws OperationException, ProvisioningException {
Path targetDir = null;
try {
targetDir = Files.createTempDirectory("update-candidate");
@@ -141,6 +144,11 @@ private boolean performUpdate(UpdateAction updateAction, boolean yes, CliConsole
final List conflicts = applyCandidateAction.getConflicts();
if (!conflicts.isEmpty()) {
FileConflictPrinter.print(conflicts, console);
+
+ if (noConflictsOnly) {
+ throw CliMessages.MESSAGES.cancelledByConfilcts();
+ }
+
if (!yes && !console.confirm(CliMessages.MESSAGES.continueWithUpdate(), "", CliMessages.MESSAGES.updateCancelled())) {
return false;
}
@@ -226,6 +234,12 @@ public static class ApplyCommand extends AbstractCommand {
@CommandLine.Option(names = {CliConstants.Y, CliConstants.YES})
boolean yes;
+ @CommandLine.Option(names = {CliConstants.NO_CONFLICTS_ONLY})
+ boolean noConflictsOnly;
+
+ @CommandLine.Option(names = {CliConstants.DRY_RUN})
+ boolean dryRun;
+
public ApplyCommand(CliConsole console, ActionFactory actionFactory) {
super(console, actionFactory);
}
@@ -257,6 +271,14 @@ public Integer call() throws Exception {
final List conflicts = applyCandidateAction.getConflicts();
FileConflictPrinter.print(conflicts, console);
+ if (dryRun) {
+ return ReturnCodes.SUCCESS;
+ }
+
+ if (noConflictsOnly && !conflicts.isEmpty()) {
+ throw CliMessages.MESSAGES.cancelledByConfilcts();
+ }
+
// there always should be updates, so confirm update
if (!yes && !console.confirm(CliMessages.MESSAGES.continueWithUpdate(), CliMessages.MESSAGES.applyingUpdates(), CliMessages.MESSAGES.updateCancelled())) {
return ReturnCodes.SUCCESS;
diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/spi/CliProviderImpl.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/spi/CliProviderImpl.java
index 4224f2d39..f0a37700f 100644
--- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/spi/CliProviderImpl.java
+++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/spi/CliProviderImpl.java
@@ -49,20 +49,22 @@ public String getScriptName(OsShell shell) {
}
@Override
- public String getApplyUpdateCommand(Path installationPath, Path candidatePath) {
+ public String getApplyUpdateCommand(Path installationPath, Path candidatePath, boolean noConflictsOnly) {
return CliConstants.Commands.UPDATE + " " + CliConstants.Commands.APPLY + " "
+ CliConstants.DIR + " " + escape(installationPath.toAbsolutePath()) + " "
+ CliConstants.CANDIDATE_DIR + " " + escape(candidatePath.toAbsolutePath()) + " "
+ CliConstants.YES + " "
+ + (noConflictsOnly ? CliConstants.NO_CONFLICTS_ONLY + " " : "")
+ CliConstants.REMOVE;
}
@Override
- public String getApplyRevertCommand(Path installationPath, Path candidatePath) {
+ public String getApplyRevertCommand(Path installationPath, Path candidatePath, boolean noConflictsOnly) {
return CliConstants.Commands.REVERT + " " + CliConstants.Commands.APPLY + " "
+ CliConstants.DIR + " " + escape(installationPath.toAbsolutePath()) + " "
+ CliConstants.CANDIDATE_DIR + " " + escape(candidatePath.toAbsolutePath()) + " "
+ CliConstants.YES + " "
+ + (noConflictsOnly ? CliConstants.NO_CONFLICTS_ONLY + " " : "")
+ CliConstants.REMOVE;
}
diff --git a/prospero-cli/src/main/resources/UsageMessages.properties b/prospero-cli/src/main/resources/UsageMessages.properties
index 385c6772a..8e4cd917b 100644
--- a/prospero-cli/src/main/resources/UsageMessages.properties
+++ b/prospero-cli/src/main/resources/UsageMessages.properties
@@ -155,7 +155,6 @@ dir = Location of the existing application server. If not specified, current wor
${prospero.dist.name}.install.dir = Target directory where the application server will be provisioned.
${prospero.dist.name}.clone.recreate.dir = Target directory where the application server will be provisioned.
-dry-run = Print components that can be upgraded, but do not perform the upgrades.
fpl.0 = Maven coordinates of a Galleon feature pack. The specified feature pack is installed \
with default layers and packages.
fpl.1 = When you use this option, you should also specify the @|bold --channels|@ or a combination of @|bold --manifest|@ \
@@ -197,6 +196,9 @@ package-stability-level.1 = Valid options are ${COMPLETION-CANDIDATES}.
${prospero.dist.name}.update.prepare.candidate-dir = Target directory where the candidate server will be provisioned. The existing server is not updated.
${prospero.dist.name}.update.subscribe.product = Specify the product name. This must be a known feature pack supported by ${prospero.dist.name}.
${prospero.dist.name}.update.subscribe.version = Specify the version of the product.
+no-conflicts-only = Rejects the operation if any file conflicts are detected. If not used, the user will be asked to \
+ confirm automatic conflict resolution, unless @|bold --yes|@ option is used.
+dry-run = Prints the changes that would be performed by executing the command, but does not perform any changes on the filesystem.
#
# Exit Codes
@@ -281,6 +283,8 @@ prospero.updates.apply.validation.candidate.wrong_type=Unable to apply candidate
prospero.updates.apply.validation.candidate.not_candidate=Unable to apply candidate.%n Installation at [%s] doesn't have a candidate marker file.
prospero.updates.apply.candidate.remove=Remove the candidate directory after applying update.
+prospero.updates.apply.candidate.cancel_conflicts = Potential conflicts exist in the installation. Resolve the conflicts in the listed files, or \
+ use [%s=false] to preserve user changes where possible.
prospero.updates.build.candidate.header=Building update candidate for %s%n
prospero.updates.build.candidate.complete=Update candidate generated in %s
diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ApplyUpdateCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ApplyUpdateCommandTest.java
index 6bd1c71e9..c39e202a7 100644
--- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ApplyUpdateCommandTest.java
+++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ApplyUpdateCommandTest.java
@@ -24,6 +24,7 @@
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.api.FileConflict;
@@ -43,6 +44,7 @@
import java.util.Collections;
import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -188,6 +190,54 @@ public void testAskForConfirmationIfConflictsPresent() throws Exception {
assertEquals(1, askedConfirmation);
}
+ @Test
+ public void noConflictArgumentFailsCommand_WhenConflictsAreFound() throws Exception {
+ final Path updatePath = mockInstallation("update");
+ final Path targetPath = mockInstallation("target");
+ when(applyCandidateAction.getConflicts()).thenReturn(List.of(mock(FileConflict.class)));
+
+ int exitCode = commandLine.execute(CliConstants.Commands.UPDATE, CliConstants.Commands.APPLY,
+ CliConstants.CANDIDATE_DIR, updatePath.toString(),
+ CliConstants.DIR, targetPath.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.PROCESSING_ERROR, exitCode);
+ assertThat(getErrorOutput())
+ .contains(CliMessages.MESSAGES.cancelledByConfilcts().getMessage());
+
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
+
+ @Test
+ public void noConflictArgumentHasNoEffect_WhenNoConflictsAreFound() throws Exception {
+ final Path updatePath = mockInstallation("update");
+ final Path targetPath = mockInstallation("target");
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.UPDATE, CliConstants.Commands.APPLY,
+ CliConstants.CANDIDATE_DIR, updatePath.toString(),
+ CliConstants.DIR, targetPath.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction).applyUpdate(ApplyCandidateAction.Type.UPDATE);
+ }
+
+ @Test
+ public void dryRun_DoesntCallApplyAction() throws Exception {
+ final Path updatePath = mockInstallation("update");
+ final Path targetPath = mockInstallation("target");
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.UPDATE, CliConstants.Commands.APPLY,
+ CliConstants.CANDIDATE_DIR, updatePath.toString(),
+ CliConstants.DIR, targetPath.toString(),
+ CliConstants.DRY_RUN);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
+
private Path mockInstallation(String target) throws IOException, MetadataException, XMLStreamException {
final Path targetPath = temp.newFolder(target).toPath();
MetadataTestUtils.createInstallationMetadata(targetPath).close();
diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertApplyCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertApplyCommandTest.java
index dce614283..5dfe1eaad 100644
--- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertApplyCommandTest.java
+++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertApplyCommandTest.java
@@ -25,10 +25,12 @@
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.api.Console;
import org.wildfly.prospero.actions.InstallationHistoryAction;
+import org.wildfly.prospero.api.FileConflict;
import org.wildfly.prospero.api.SavedState;
import org.wildfly.prospero.api.exceptions.OperationException;
import org.wildfly.prospero.cli.AbstractConsoleTest;
@@ -40,9 +42,13 @@
import java.nio.file.Path;
import java.util.Collections;
+import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -119,4 +125,46 @@ public void callApplyOperation() throws Exception {
assertEquals(ReturnCodes.SUCCESS, exitCode);
verify(applyCandidateAction).applyUpdate(ApplyCandidateAction.Type.REVERT);
}
+
+ @Test
+ public void noConflictArgumentFailsCommand_WhenConflictsAreFound() throws Exception {
+ when(applyCandidateAction.getConflicts()).thenReturn(List.of(mock(FileConflict.class)));
+
+ int exitCode = commandLine.execute(CliConstants.Commands.REVERT, CliConstants.Commands.APPLY,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.CANDIDATE_DIR, updateDir.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.PROCESSING_ERROR, exitCode);
+ assertThat(getErrorOutput())
+ .contains(CliMessages.MESSAGES.cancelledByConfilcts().getMessage());
+
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
+
+ @Test
+ public void noConflictArgumentHasNoEffect_WhenNoConflictsAreFound() throws Exception {
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.REVERT, CliConstants.Commands.APPLY,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.CANDIDATE_DIR, updateDir.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction).applyUpdate(ApplyCandidateAction.Type.REVERT);
+ }
+
+ @Test
+ public void dryRun_DoesntCallApplyAction() throws Exception {
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.REVERT, CliConstants.Commands.APPLY,
+ CliConstants.CANDIDATE_DIR, updateDir.toString(),
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.DRY_RUN);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
}
diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertPerformCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertPerformCommandTest.java
index 843f9f8d5..652e285f5 100644
--- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertPerformCommandTest.java
+++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/RevertPerformCommandTest.java
@@ -31,11 +31,13 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.wildfly.channel.Repository;
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.api.Console;
import org.wildfly.prospero.actions.InstallationHistoryAction;
+import org.wildfly.prospero.api.FileConflict;
import org.wildfly.prospero.api.MavenOptions;
import org.wildfly.prospero.api.SavedState;
import org.wildfly.prospero.api.exceptions.OperationException;
@@ -50,6 +52,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -154,6 +157,35 @@ public void passRemoteRepositories() throws Exception {
.containsExactly("http://temp.repo.te");
}
+ @Test
+ public void noConflictArgumentFailsCommand_WhenConflictsAreFound() throws Exception {
+ when(applyCandidateAction.getConflicts()).thenReturn(List.of(mock(FileConflict.class)));
+
+ int exitCode = commandLine.execute(CliConstants.Commands.REVERT, CliConstants.Commands.PERFORM,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.REVISION, "abcd",
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.PROCESSING_ERROR, exitCode);
+ assertThat(getErrorOutput())
+ .contains(CliMessages.MESSAGES.cancelledByConfilcts().getMessage());
+
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
+
+ @Test
+ public void noConflictArgumentHasNoEffect_WhenNoConflictsAreFound() throws Exception {
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.REVERT, CliConstants.Commands.PERFORM,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.REVISION, "abcd",
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction).applyUpdate(ApplyCandidateAction.Type.REVERT);
+ }
+
@Override
protected MavenOptions getCapturedMavenOptions() throws Exception {
verify(historyAction).prepareRevert(eq(new SavedState("abcd")), mavenOptions.capture(), any(), any());
diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/UpdateCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/UpdateCommandTest.java
index 7b76e4052..855a40f56 100644
--- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/UpdateCommandTest.java
+++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/UpdateCommandTest.java
@@ -39,6 +39,7 @@
import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.actions.UpdateAction;
import org.wildfly.prospero.api.ArtifactChange;
+import org.wildfly.prospero.api.FileConflict;
import org.wildfly.prospero.api.MavenOptions;
import org.wildfly.prospero.cli.ActionFactory;
import org.wildfly.prospero.cli.CliMessages;
@@ -51,7 +52,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
@@ -303,6 +306,37 @@ public void spliRepositoriesFromArgument() throws Exception {
}
+ @Test
+ public void noConflictArgumentFailsCommand_WhenConflictsAreFound() throws Exception {
+ when(updateAction.findUpdates()).thenReturn(new UpdateSet(List.of(change("1.0.0", "1.0.1"))));
+ when(updateAction.buildUpdate(any())).thenReturn(true);
+ when(applyCandidateAction.getConflicts()).thenReturn(List.of(mock(FileConflict.class)));
+
+ int exitCode = commandLine.execute(CliConstants.Commands.UPDATE, CliConstants.Commands.PERFORM,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.PROCESSING_ERROR, exitCode);
+ assertThat(getErrorOutput())
+ .contains(CliMessages.MESSAGES.cancelledByConfilcts().getMessage());
+
+ verify(applyCandidateAction, Mockito.never()).applyUpdate(any());
+ }
+
+ @Test
+ public void noConflictArgumentHasNoEffect_WhenNoConflictsAreFound() throws Exception {
+ when(updateAction.findUpdates()).thenReturn(new UpdateSet(List.of(change("1.0.0", "1.0.1"))));
+ when(updateAction.buildUpdate(any())).thenReturn(true);
+ when(applyCandidateAction.getConflicts()).thenReturn(Collections.emptyList());
+
+ int exitCode = commandLine.execute(CliConstants.Commands.UPDATE, CliConstants.Commands.PERFORM,
+ CliConstants.DIR, installationDir.toString(),
+ CliConstants.NO_CONFLICTS_ONLY);
+
+ assertEquals(ReturnCodes.SUCCESS, exitCode);
+ verify(applyCandidateAction).applyUpdate(ApplyCandidateAction.Type.UPDATE);
+ }
+
private ArtifactChange change(String oldVersion, String newVersion) {
return ArtifactChange.updated(new DefaultArtifact("org.foo", "bar", null, oldVersion),
new DefaultArtifact("org.foo", "bar", null, newVersion));
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/ProsperoLogger.java b/prospero-common/src/main/java/org/wildfly/prospero/ProsperoLogger.java
index cab8ff124..bba33737a 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/ProsperoLogger.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/ProsperoLogger.java
@@ -26,6 +26,7 @@
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
import org.wildfly.channel.InvalidChannelMetadataException;
+import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.actions.FeaturesAddAction;
import org.wildfly.prospero.api.exceptions.ArtifactPromoteException;
import org.wildfly.prospero.api.exceptions.ChannelDefinitionException;
@@ -392,4 +393,14 @@ public interface ProsperoLogger extends BasicLogger {
@Message(id = 272, value = "Failed to apply the candidate changes due to: %s")
String failedToApplyCandidate(String reason);
+
+ @Message(id = 273, value = "The server [%s] has been modified after the candidate has been created [%s].")
+ InvalidUpdateCandidateException staleCandidate(Path originalServer, Path candiadate);
+
+ @Message(id = 274, value = "The folder [%s] doesn't contain a server candidate.")
+ InvalidUpdateCandidateException notCandidate(Path candidateServer);
+
+ @Message(id = 275, value = "The candidate at [%s] was not prepared for %s operation.")
+ InvalidUpdateCandidateException wrongCandidateOperation(Path candidateServer, ApplyCandidateAction.Type operationType);
+
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/FeaturesAddAction.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/FeaturesAddAction.java
index 925e1b175..6cd3aab1e 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/actions/FeaturesAddAction.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/actions/FeaturesAddAction.java
@@ -753,9 +753,9 @@ public PrepareCandidateAction newPrepareCandidateActionInstance(
}
@Override
- public ApplyCandidateAction newApplyCandidateActionInstance(Path candidateDir)
+ public ApplyCandidateAction newApplyCandidateActionInstance(Path candidatePath)
throws ProvisioningException, OperationException {
- return new ApplyCandidateAction(installDir, candidateDir);
+ return new ApplyCandidateAction(installDir, candidatePath);
}
}
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/InstallationHistoryAction.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/InstallationHistoryAction.java
index 727508f19..8f479894f 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/actions/InstallationHistoryAction.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/actions/InstallationHistoryAction.java
@@ -142,7 +142,7 @@ public void prepareRevert(SavedState savedState, MavenOptions mavenOptions, List
prepareCandidateAction.buildCandidate(targetDir, galleonEnv,
ApplyCandidateAction.Type.REVERT, provisioningConfig,
- UpdateSet.EMPTY, (channels) -> revertMetadata.getManifestVersions());
+ UpdateSet.EMPTY, revertMetadata::getManifestVersions);
}
ProsperoLogger.ROOT_LOGGER.revertCandidateCompleted(targetDir);
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/PrepareCandidateAction.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/PrepareCandidateAction.java
index edbfd2199..f75fd9da0 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/actions/PrepareCandidateAction.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/actions/PrepareCandidateAction.java
@@ -17,6 +17,8 @@
package org.wildfly.prospero.actions;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
import org.jboss.galleon.Constants;
import org.jboss.galleon.ProvisioningException;
import org.jboss.logging.Logger;
@@ -36,6 +38,7 @@
import org.wildfly.prospero.galleon.GalleonUtils;
import org.wildfly.prospero.licenses.LicenseManager;
import org.wildfly.prospero.metadata.ManifestVersionRecord;
+import org.wildfly.prospero.metadata.ManifestVersionResolver;
import org.wildfly.prospero.metadata.ProsperoMetadataUtils;
import org.wildfly.prospero.model.ProsperoConfig;
import org.wildfly.prospero.updates.CandidateProperties;
@@ -51,7 +54,8 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.function.Function;
+import java.util.function.Supplier;
+
import org.jboss.galleon.api.Provisioning;
import org.jboss.galleon.api.config.GalleonProvisioningConfig;
@@ -91,7 +95,7 @@ boolean buildCandidate(Path targetDir, GalleonEnvironment galleonEnv, ApplyCandi
*/
boolean buildCandidate(Path targetDir, GalleonEnvironment galleonEnv, ApplyCandidateAction.Type operation,
GalleonProvisioningConfig config, UpdateSet updateSet) throws ProvisioningException, OperationException {
- return this.buildCandidate(targetDir, galleonEnv, operation, config, updateSet, this::getManifestVersionRecord);
+ return this.buildCandidate(targetDir, galleonEnv, operation, config, updateSet, () -> getManifestVersionRecord(galleonEnv));
}
/**
@@ -110,7 +114,7 @@ boolean buildCandidate(Path targetDir, GalleonEnvironment galleonEnv, ApplyCandi
*/
boolean buildCandidate(Path targetDir, GalleonEnvironment galleonEnv, ApplyCandidateAction.Type operation,
GalleonProvisioningConfig config, UpdateSet updateSet,
- Function, Optional> manifestVersionRecordSupplier) throws ProvisioningException, OperationException {
+ Supplier> manifestVersionRecordSupplier) throws ProvisioningException, OperationException {
Objects.requireNonNull(manifestVersionRecordSupplier);
doBuildUpdate(targetDir, galleonEnv, config, manifestVersionRecordSupplier);
@@ -127,7 +131,7 @@ boolean buildCandidate(Path targetDir, GalleonEnvironment galleonEnv, ApplyCandi
}
private void doBuildUpdate(Path targetDir, GalleonEnvironment galleonEnv, GalleonProvisioningConfig provisioningConfig,
- Function, Optional> manifestVersionResolver)
+ Supplier> manifestVersionResolver)
throws ProvisioningException, OperationException {
final Provisioning provMgr = galleonEnv.getProvisioning();
try {
@@ -142,7 +146,7 @@ private void doBuildUpdate(Path targetDir, GalleonEnvironment galleonEnv, Galleo
}
- final Optional manifestRecord = manifestVersionResolver.apply(galleonEnv.getChannels());
+ final Optional manifestRecord = manifestVersionResolver.get();
if (LOG.isTraceEnabled()) {
LOG.tracef("Recording manifests: %s", manifestRecord.orElse(new ManifestVersionRecord()));
@@ -165,10 +169,9 @@ private void doBuildUpdate(Path targetDir, GalleonEnvironment galleonEnv, Galleo
}
}
- private Optional getManifestVersionRecord(List channels) {
- final ProsperoManifestVersionResolver manifestResolver = new ProsperoManifestVersionResolver(mavenSessionManager);
+ private Optional getManifestVersionRecord(GalleonEnvironment galleonEnv) {
try {
- return Optional.of(manifestResolver.getCurrentVersions(channels));
+ return Optional.of(ManifestVersionResolver.getCurrentVersions(galleonEnv.getChannelSession()));
} catch (IOException e) {
ProsperoLogger.ROOT_LOGGER.debug("Unable to retrieve current manifest versions", e);
return Optional.empty();
@@ -177,7 +180,10 @@ private Optional getManifestVersionRecord(List c
private void cacheManifests(ManifestVersionRecord manifestRecord, Path installDir) {
try {
- ArtifactCache.getInstance(installDir).cache(manifestRecord, mavenSessionManager.getResolvedArtifactVersions());
+ final RepositorySystem system = mavenSessionManager.newRepositorySystem();
+ final DefaultRepositorySystemSession session = mavenSessionManager.newRepositorySystemSession(system);
+
+ ArtifactCache.getInstance(installDir).cache(manifestRecord, session.getLocalRepositoryManager());
} catch (IOException e) {
ProsperoLogger.ROOT_LOGGER.debug("Unable to record manifests in the internal cache", e);
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolver.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolver.java
deleted file mode 100644
index 190d9f8e5..000000000
--- a/prospero-common/src/main/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolver.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2024 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.wildfly.prospero.actions;
-
-import org.jboss.logging.Logger;
-import org.wildfly.channel.Channel;
-import org.wildfly.channel.ChannelManifestMapper;
-import org.wildfly.channel.MavenArtifact;
-import org.wildfly.channel.MavenCoordinate;
-import org.wildfly.prospero.metadata.ManifestVersionRecord;
-import org.wildfly.prospero.metadata.ManifestVersionResolver;
-import org.wildfly.prospero.wfchannel.MavenSessionManager;
-import org.wildfly.prospero.wfchannel.ResolvedArtifactsStore;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * Identifies manifests used to provision installation.
- * It uses {@code ResolvedManifestVersions} to find already resolved manifests and falls back onto
- * {@code ManifestVersionResolver} if not possible.
- */
-class ProsperoManifestVersionResolver {
-
- private static final Logger LOG = Logger.getLogger(ProsperoManifestVersionResolver.class.getName());
-
- private final ResolvedArtifactsStore manifestVersions;
-
- private final Supplier manifestVersionResolver;
-
- ProsperoManifestVersionResolver(MavenSessionManager mavenSessionManager) {
- this.manifestVersions = mavenSessionManager.getResolvedArtifactVersions();
- this.manifestVersionResolver = () -> new ManifestVersionResolver(
- mavenSessionManager.getProvisioningRepo(),
- mavenSessionManager.newRepositorySystem());
- }
-
- ProsperoManifestVersionResolver(ResolvedArtifactsStore manifestVersions, ManifestVersionResolver manifestVersionResolver) {
- this.manifestVersions = manifestVersions;
- this.manifestVersionResolver = () -> manifestVersionResolver;
- }
-
- /**
- * attempt to resolve the current versions from artifacts recorded during provisioning.
- * Fallback on artifacts in the local maven cache if not available.
- *
- * @param channels
- * @return
- * @throws IOException
- */
- public ManifestVersionRecord getCurrentVersions(List channels) throws IOException {
- final ManifestVersionRecord record = new ManifestVersionRecord();
- final ArrayList fallbackChannels = new ArrayList<>();
- for (Channel channel : channels) {
- if (channel.getManifestCoordinate().getMaven() != null && channel.getManifestCoordinate().getMaven().getVersion() == null) {
- final MavenCoordinate manifestCoord = channel.getManifestCoordinate().getMaven();
- if (LOG.isDebugEnabled()) {
- LOG.debugf("Trying to lookup manifest %s", manifestCoord);
- }
- final MavenArtifact version = manifestVersions.getManifestVersion(manifestCoord.getGroupId(), manifestCoord.getArtifactId());
- if (version == null) {
- if (LOG.isDebugEnabled()) {
- LOG.debugf("Failed to lookup manifest %s in currently resolved artifacts", manifestCoord);
- }
- fallbackChannels.add(channel);
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debugf("Manifest %s resolved in currently resolve artifacts, recording.", manifestCoord);
- }
- final String description = ChannelManifestMapper.from(version.getFile().toURI().toURL()).getDescription();
- record.addManifest(new ManifestVersionRecord.MavenManifest(
- manifestCoord.getGroupId(),
- manifestCoord.getArtifactId(),
- version.getVersion(),
- description));
- }
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debugf("Manifest for channel %s will be resolved via fallback.", channel.getName());
- }
- fallbackChannels.add(channel);
- }
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debugf("Resolving channel manifests using fallback mechanisms.");
- }
- final ManifestVersionRecord currentVersions = manifestVersionResolver.get().getCurrentVersions(fallbackChannels);
- currentVersions.getMavenManifests().forEach(record::addManifest);
- currentVersions.getOpenManifests().forEach(record::addManifest);
- currentVersions.getUrlManifests().forEach(record::addManifest);
-
- return record;
- }
-}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/ProvisioningAction.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/ProvisioningAction.java
index 212395fcc..7bca82a87 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/actions/ProvisioningAction.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/actions/ProvisioningAction.java
@@ -18,6 +18,8 @@
package org.wildfly.prospero.actions;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.resolution.ArtifactResult;
import org.jboss.galleon.universe.maven.MavenUniverseException;
import org.wildfly.channel.ArtifactCoordinate;
@@ -143,8 +145,7 @@ public void provision(GalleonProvisioningConfig provisioningConfig, List version = manifestRecord.getMavenManifests().stream()
+ .filter(m -> m.getGroupId().equals(groupId) && m.getArtifactId().equals(artifactId))
+ .map(ManifestVersionRecord.MavenManifest::getVersion)
+ .findFirst();
+ return version
+ .map(v -> localRepositoryManager.getPathForLocalArtifact(new DefaultArtifact(groupId, artifactId, ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION, v)))
+ .map(p -> localRepositoryManager.getRepository().getBasedir().toPath().resolve(p).toFile())
+ .map(f -> new MavenArtifact(groupId, artifactId, ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, version.get(), f))
+ .orElse(null);
+ }
+
private void init() throws IOException {
Path artifactLog = cacheDir.resolve(CACHE_FILENAME);
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/galleon/CachedVersionResolver.java b/prospero-common/src/main/java/org/wildfly/prospero/galleon/CachedVersionResolver.java
index 31de22592..be5871045 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/galleon/CachedVersionResolver.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/galleon/CachedVersionResolver.java
@@ -17,9 +17,6 @@
package org.wildfly.prospero.galleon;
-import org.eclipse.aether.AbstractRepositoryListener;
-import org.eclipse.aether.RepositoryEvent;
-import org.eclipse.aether.RepositoryListener;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.DefaultArtifact;
@@ -28,6 +25,7 @@
import org.jboss.logging.Logger;
import org.wildfly.channel.ArtifactCoordinate;
import org.wildfly.channel.ArtifactTransferException;
+import org.wildfly.channel.ChannelManifest;
import org.wildfly.channel.ChannelMetadataCoordinate;
import org.wildfly.channel.UnresolvedMavenArtifactException;
import org.wildfly.channel.spi.MavenVersionsResolver;
@@ -51,15 +49,12 @@
*/
public class CachedVersionResolver implements MavenVersionsResolver {
private static final Logger LOG = Logger.getLogger(CachedVersionResolver.class.getName());
-
- private static final RepositoryListener NOOP_REPOSITORY_LISTENER = new AbstractRepositoryListener(){};
private final MavenVersionsResolver fallbackResolver;
private final RepositorySystem system;
private final RepositorySystemSession session;
private final ArtifactCache artifactCache;
private final Logger log = Logger.getLogger(CachedVersionResolver.class);
- private final RepositoryListener listener;
private final Function manifestVersionProvider;
public CachedVersionResolver(MavenVersionsResolver fallbackResolver, ArtifactCache cache, RepositorySystem system,
@@ -70,12 +65,30 @@ public CachedVersionResolver(MavenVersionsResolver fallbackResolver, ArtifactCac
this.session = session;
this.artifactCache = cache;
this.manifestVersionProvider = manifestVersionProvider;
- this.listener = session.getRepositoryListener() != null ? session.getRepositoryListener() : NOOP_REPOSITORY_LISTENER;
}
@Override
public Set getAllVersions(String groupId, String artifactId, String extension, String classifier) {
- return fallbackResolver.getAllVersions(groupId, artifactId, extension, classifier);
+ final Set allVersions = fallbackResolver.getAllVersions(groupId, artifactId, extension, classifier);
+
+ if (!allVersions.isEmpty()) {
+ return allVersions;
+ } else {
+ if (ChannelManifest.EXTENSION.equals(extension) && ChannelManifest.CLASSIFIER.equals(classifier)) {
+
+ ArtifactCoordinate a = new ArtifactCoordinate(groupId, artifactId, extension, classifier, "");
+ // get version from manifest_versions to verify this is the latest version
+ final String version = manifestVersionProvider.apply(a);
+ if (LOG.isDebugEnabled()) {
+ LOG.debugf("Last used version for manifest %s is %s.", a, version);
+ }
+
+ if (version != null) {
+ return Set.of(version);
+ }
+ }
+ return allVersions;
+ }
}
@Override
@@ -158,17 +171,23 @@ public List resolveChannelMetadata(List extends ChannelMetadataCoordinate
LOG.debugf("Found cached manifest for %s.", a);
}
log.warnf("Unable to resolve manifest for channel %s, no updates will be resolved for this channel.", a);
- this.listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(new DefaultArtifact(
- a.getGroupId(),
- a.getArtifactId(),
- a.getClassifier(),
- a.getExtension(),
- version,
- null,
- artifact.get()
- ))
- .build());
+ installArtifactLocally(a.getGroupId(),
+ a.getArtifactId(),
+ a.getExtension(),
+ a.getClassifier(),
+ version,
+ artifact.get());
+// this.listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
+// .setArtifact(new DefaultArtifact(
+// a.getGroupId(),
+// a.getArtifactId(),
+// a.getClassifier(),
+// a.getExtension(),
+// version,
+// null,
+// artifact.get()
+// ))
+// .build());
try {
// maintain order as in manifestCoords
for (int i = 0; i < manifestCoords.size(); i++) {
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java b/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java
index 1568b69a5..5f2c4d376 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java
@@ -5,8 +5,10 @@
import org.wildfly.channel.ChannelManifestCoordinate;
import org.wildfly.channel.MavenCoordinate;
import org.wildfly.installationmanager.ArtifactChange;
+import org.wildfly.installationmanager.CandidateType;
import org.wildfly.installationmanager.Channel;
import org.wildfly.installationmanager.ChannelChange;
+import org.wildfly.installationmanager.FileConflict;
import org.wildfly.installationmanager.HistoryResult;
import org.wildfly.installationmanager.InstallationChanges;
import org.wildfly.installationmanager.ManifestVersion;
@@ -16,11 +18,13 @@
import org.wildfly.installationmanager.spi.InstallationManager;
import org.wildfly.installationmanager.spi.OsShell;
import org.wildfly.prospero.ProsperoLogger;
+import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.actions.InstallationExportAction;
import org.wildfly.prospero.actions.InstallationHistoryAction;
import org.wildfly.prospero.actions.MetadataAction;
import org.wildfly.prospero.actions.UpdateAction;
import org.wildfly.prospero.api.MavenOptions.Builder;
+import org.wildfly.prospero.api.exceptions.InvalidUpdateCandidateException;
import org.wildfly.prospero.galleon.GalleonCallbackAdapter;
import org.wildfly.prospero.metadata.ManifestVersionRecord;
import org.wildfly.prospero.spi.internal.CliProvider;
@@ -76,7 +80,8 @@ public List history() throws Exception {
final List results = new ArrayList<>();
for (SavedState savedState : revisions) {
- results.add(new HistoryResult(savedState.getName(), savedState.getTimestamp(), savedState.getType().toString(), savedState.getMsg()));
+ results.add(new HistoryResult(savedState.getName(), savedState.getTimestamp(), savedState.getType().toString(),
+ savedState.getMsg(), Collections.emptyList()));
}
return results;
}
@@ -117,6 +122,61 @@ public boolean prepareUpdate(Path targetDir, List repositories) thro
}
}
+ @Override
+ public Collection verifyCandidate(Path candidatePath, CandidateType candidateType) throws Exception {
+ final ApplyCandidateAction applyCandidateAction = actionFactory.getApplyCandidateAction(candidatePath);
+ final ApplyCandidateAction.Type operation;
+ switch (candidateType) {
+ case UPDATE:
+ operation = ApplyCandidateAction.Type.UPDATE;
+ break;
+ case REVERT:
+ operation = ApplyCandidateAction.Type.REVERT;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported candidate type: " + candidateType);
+ }
+
+ final ApplyCandidateAction.ValidationResult validationResult = applyCandidateAction.verifyCandidate(operation);
+ switch (validationResult) {
+ case OK:
+ // we're good, continue
+ break;
+ case STALE:
+ throw ProsperoLogger.ROOT_LOGGER.staleCandidate(installationDir, candidatePath);
+ case NO_CHANGES:
+ throw ProsperoLogger.ROOT_LOGGER.noChangesAvailable(installationDir, candidatePath);
+ case NOT_CANDIDATE:
+ throw ProsperoLogger.ROOT_LOGGER.notCandidate(candidatePath);
+ case WRONG_TYPE:
+ throw ProsperoLogger.ROOT_LOGGER.wrongCandidateOperation(candidatePath, operation);
+ default:
+ // unexpected validation type - include the error in the description
+ throw new InvalidUpdateCandidateException(String.format("The candidate server %s is invalid - %s.", candidatePath, validationResult));
+ }
+
+ return map(applyCandidateAction.getConflicts(), ProsperoInstallationManager::mapFileConflict);
+ }
+
+ private static FileConflict mapFileConflict(org.wildfly.prospero.api.FileConflict fileConflict) {
+ return new FileConflict(Path.of(fileConflict.getRelativePath()), map(fileConflict.getUserChange()), map(fileConflict.getUpdateChange()), fileConflict.getResolution() == org.wildfly.prospero.api.FileConflict.Resolution.UPDATE);
+ }
+
+ private static FileConflict.Status map(org.wildfly.prospero.api.FileConflict.Change change) {
+ switch (change) {
+ case MODIFIED:
+ return FileConflict.Status.MODIFIED;
+ case ADDED:
+ return FileConflict.Status.ADDED;
+ case REMOVED:
+ return FileConflict.Status.REMOVED;
+ case NONE:
+ return FileConflict.Status.NONE;
+ default:
+ throw new IllegalArgumentException("Unknown file conflict change: " + change);
+ }
+ }
+
@Override
public List findUpdates(List repositories) throws Exception {
try (UpdateAction updateAction = actionFactory.getUpdateAction(map(repositories, ProsperoInstallationManager::mapRepository))) {
@@ -197,24 +257,34 @@ public String generateApplyRevertCommand(Path scriptHome, Path candidatePath) th
@Override
public String generateApplyUpdateCommand(Path scriptHome, Path candidatePath, OsShell shell) throws OperationNotAvailableException {
+ return generateApplyUpdateCommand(scriptHome, candidatePath, shell, false);
+ }
+
+ @Override
+ public String generateApplyRevertCommand(Path scriptHome, Path candidatePath, OsShell shell) throws OperationNotAvailableException {
+ return generateApplyUpdateCommand(scriptHome, candidatePath, shell, false);
+ }
+
+ @Override
+ public String generateApplyUpdateCommand(Path scriptHome, Path candidatePath, OsShell shell, boolean noConflictsOnly) throws OperationNotAvailableException {
final Optional cliProviderLoader = ServiceLoader.load(CliProvider.class).findFirst();
if (cliProviderLoader.isEmpty()) {
throw new OperationNotAvailableException("Installation manager does not support CLI operations.");
}
final CliProvider cliProvider = cliProviderLoader.get();
- return escape(scriptHome.resolve(cliProvider.getScriptName(shell))) + " " + cliProvider.getApplyUpdateCommand(installationDir, candidatePath);
+ return escape(scriptHome.resolve(cliProvider.getScriptName(shell))) + " " + cliProvider.getApplyUpdateCommand(installationDir, candidatePath, false);
}
@Override
- public String generateApplyRevertCommand(Path scriptHome, Path candidatePath, OsShell shell) throws OperationNotAvailableException {
+ public String generateApplyRevertCommand(Path scriptHome, Path candidatePath, OsShell shell, boolean noConflictsOnly) throws OperationNotAvailableException {
final Optional cliProviderLoader = ServiceLoader.load(CliProvider.class).findFirst();
if (cliProviderLoader.isEmpty()) {
throw new OperationNotAvailableException("Installation manager does not support CLI operations.");
}
final CliProvider cliProvider = cliProviderLoader.get();
- return escape(scriptHome.resolve(cliProvider.getScriptName(shell))) + " " + cliProvider.getApplyRevertCommand(installationDir, candidatePath);
+ return escape(scriptHome.resolve(cliProvider.getScriptName(shell))) + " " + cliProvider.getApplyRevertCommand(installationDir, candidatePath, noConflictsOnly);
}
@Override
@@ -345,6 +415,10 @@ protected InstallationExportAction getInstallationExportAction() {
return new InstallationExportAction(server);
}
+ protected ApplyCandidateAction getApplyCandidateAction(Path candidateDir) throws ProvisioningException, OperationException {
+ return new ApplyCandidateAction(server, candidateDir);
+ }
+
org.wildfly.prospero.api.MavenOptions getMavenOptions() {
return mavenOptions;
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/spi/internal/CliProvider.java b/prospero-common/src/main/java/org/wildfly/prospero/spi/internal/CliProvider.java
index d29d6ac75..a4f4a7c20 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/spi/internal/CliProvider.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/spi/internal/CliProvider.java
@@ -37,16 +37,18 @@ public interface CliProvider {
*
* @param installationPath
* @param candidatePath
+ * @param noConflictsOnly - whether to append the no-conflicts-only flag
* @return
*/
- String getApplyUpdateCommand(Path installationPath, Path candidatePath);
+ String getApplyUpdateCommand(Path installationPath, Path candidatePath, boolean noConflictsOnly);
/**
* generates command used to apply a revert candidate in {@code candidatePath} into {@code installationPath}
*
* @param installationPath
* @param candidatePath
+ * @param noConflictsOnly - whether to append the no-conflicts-only flag
* @return
*/
- String getApplyRevertCommand(Path installationPath, Path candidatePath);
+ String getApplyRevertCommand(Path installationPath, Path candidatePath, boolean noConflictsOnly);
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/MavenSessionManager.java b/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/MavenSessionManager.java
index 8fc901a17..fe12e7558 100644
--- a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/MavenSessionManager.java
+++ b/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/MavenSessionManager.java
@@ -44,7 +44,6 @@ public class MavenSessionManager {
private static final String AETHER_OFFLINE_PROTOCOLS_PROPERTY = "aether.offline.protocols";
public static final String AETHER_OFFLINE_PROTOCOLS_VALUE = "file";
private final Path provisioningRepo;
- private final ProsperoMavenRepositoryListener repositoryListener = new ProsperoMavenRepositoryListener();
private boolean offline;
public MavenSessionManager(MavenOptions mavenOptions) throws ProvisioningException {
@@ -100,7 +99,6 @@ public DefaultRepositorySystemSession newRepositorySystemSession(RepositorySyste
final DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
final LocalRepository localRepo = new LocalRepository(provisioningRepo.toAbsolutePath().toFile());
- session.setRepositoryListener(repositoryListener);
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
session.setOffline(offline);
return session;
@@ -117,13 +115,4 @@ public void setOffline(boolean offline) {
public boolean isOffline() {
return offline;
}
-
- /**
- * returns a {@code ResolvedArtifactsStore} containing artifacts resolved during that maven session.
- *
- * @return
- */
- public ResolvedArtifactsStore getResolvedArtifactVersions() {
- return repositoryListener;
- }
}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListener.java b/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListener.java
deleted file mode 100644
index 2ea5f9900..000000000
--- a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListener.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2024 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.wildfly.prospero.wfchannel;
-
-import org.eclipse.aether.AbstractRepositoryListener;
-import org.eclipse.aether.RepositoryEvent;
-import org.eclipse.aether.artifact.Artifact;
-import org.wildfly.channel.ChannelManifest;
-import org.wildfly.channel.MavenArtifact;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * listener called every time an artifact is resolved by Maven. Keeps track of artifacts resolved by Maven
- */
-class ProsperoMavenRepositoryListener extends AbstractRepositoryListener implements ResolvedArtifactsStore {
-
- private final Map manifestVersions = new HashMap<>();
-
- @Override
- public MavenArtifact getManifestVersion(String groupId, String artifactId) {
- return manifestVersions.get(getKey(groupId, artifactId, ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION));
- }
-
- @Override
- public void artifactResolved(RepositoryEvent event) {
- final Artifact a = event.getArtifact();
-
- if (a == null || a.getFile() == null) {
- return;
- }
-
- if (a.getClassifier() != null && a.getClassifier().equals(ChannelManifest.CLASSIFIER)) {
- manifestVersions.put(getKey(a),
- new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getExtension(), a.getClassifier(), a.getVersion(), a.getFile()));
- }
- }
-
- private static String getKey(Artifact a) {
- return getKey(a.getGroupId(), a.getArtifactId(), a.getClassifier(), a.getExtension());
- }
-
- private static String getKey(String groupId, String artifactId, String classifier, String extension) {
- return String.format("%s:%s:%s:%s", groupId, artifactId, nullable(classifier), nullable(extension));
- }
-
- private static String nullable(String txt) {
- if (txt == null) {
- return "";
- }
- return txt;
- }
-}
diff --git a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ResolvedArtifactsStore.java b/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ResolvedArtifactsStore.java
deleted file mode 100644
index 298155705..000000000
--- a/prospero-common/src/main/java/org/wildfly/prospero/wfchannel/ResolvedArtifactsStore.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2024 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.wildfly.prospero.wfchannel;
-
-import org.wildfly.channel.MavenArtifact;
-
-/**
- * a collection of artifacts resolved in the maven session
- */
-public interface ResolvedArtifactsStore {
-
- /**
- * queries the store to find a manifest resolved in this maven session matching the {@code GA}
- *
- * @param groupId - the {@code groupId} of the manifest
- * @param artifactId - the {@code artifactId} of the manifest
- * @return - {@code MavenArtifact} representing the resolved manifest or {@code null} if the manifest has not been resolved
- */
- MavenArtifact getManifestVersion(String groupId, String artifactId);
-}
diff --git a/prospero-common/src/main/resources/prospero-installation-profiles.yaml b/prospero-common/src/main/resources/prospero-installation-profiles.yaml
index 73372dada..454e4668d 100644
--- a/prospero-common/src/main/resources/prospero-installation-profiles.yaml
+++ b/prospero-common/src/main/resources/prospero-installation-profiles.yaml
@@ -14,4 +14,36 @@
manifest:
maven:
groupId: "org.wildfly.channels"
- artifactId: "wildfly"
\ No newline at end of file
+ artifactId: "wildfly"
+- name: "wildfly-ee"
+ galleonConfiguration: "classpath:wildfly-ee-provisioning.xml"
+ channels:
+ - schemaVersion: "2.0.0"
+ name: "wildfly-ee"
+ repositories:
+ - id: "central"
+ url: "https://repo1.maven.org/maven2/"
+ - id: "jboss-public"
+ url: "https://repository.jboss.org/nexus/content/groups/public/"
+ - id: "mrrc"
+ url: "https://maven.repository.redhat.com/ga/"
+ manifest:
+ maven:
+ groupId: "org.wildfly.channels"
+ artifactId: "wildfly-ee"
+- name: "wildfly-preview"
+ galleonConfiguration: "classpath:wildfly-preview-provisioning.xml"
+ channels:
+ - schemaVersion: "2.0.0"
+ name: "wildfly-preview"
+ repositories:
+ - id: "central"
+ url: "https://repo1.maven.org/maven2/"
+ - id: "jboss-public"
+ url: "https://repository.jboss.org/nexus/content/groups/public/"
+ - id: "mrrc"
+ url: "https://maven.repository.redhat.com/ga/"
+ manifest:
+ maven:
+ groupId: "org.wildfly.channels"
+ artifactId: "wildfly-preview"
\ No newline at end of file
diff --git a/prospero-common/src/main/resources/wildfly-ee-provisioning.xml b/prospero-common/src/main/resources/wildfly-ee-provisioning.xml
new file mode 100644
index 000000000..602793181
--- /dev/null
+++ b/prospero-common/src/main/resources/wildfly-ee-provisioning.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/prospero-common/src/main/resources/wildfly-preview-provisioning.xml b/prospero-common/src/main/resources/wildfly-preview-provisioning.xml
new file mode 100644
index 000000000..f6c22b013
--- /dev/null
+++ b/prospero-common/src/main/resources/wildfly-preview-provisioning.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/prospero-common/src/test/java/org/wildfly/channel/ChannelSessionTest.java b/prospero-common/src/test/java/org/wildfly/channel/ChannelSessionTest.java
index 09631cca0..77b06c590 100644
--- a/prospero-common/src/test/java/org/wildfly/channel/ChannelSessionTest.java
+++ b/prospero-common/src/test/java/org/wildfly/channel/ChannelSessionTest.java
@@ -53,6 +53,7 @@ public void testExceptionShouldContainMissingUrlOnManifestNotFound() throws Exce
Assert.assertTrue(e.getCause() instanceof FileNotFoundException);
Assert.assertEquals("file:idontexist.yaml" ,e.getValidationMessages().get(0));
} catch (Exception e) {
+ e.printStackTrace();
Assert.fail("Expecting " + InvalidChannelMetadataException.class + " but " + e.getClass() + " was thrown");
}
}
diff --git a/prospero-common/src/test/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolverTest.java b/prospero-common/src/test/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolverTest.java
deleted file mode 100644
index 88000f561..000000000
--- a/prospero-common/src/test/java/org/wildfly/prospero/actions/ProsperoManifestVersionResolverTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2024 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.wildfly.prospero.actions;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.wildfly.channel.Channel;
-import org.wildfly.channel.ChannelManifest;
-import org.wildfly.channel.ChannelManifestCoordinate;
-import org.wildfly.channel.ChannelManifestMapper;
-import org.wildfly.channel.MavenArtifact;
-import org.wildfly.prospero.metadata.ManifestVersionRecord;
-import org.wildfly.prospero.metadata.ManifestVersionResolver;
-import org.wildfly.prospero.wfchannel.ResolvedArtifactsStore;
-
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Files;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-
-@RunWith(MockitoJUnitRunner.class)
-public class ProsperoManifestVersionResolverTest {
- protected static final String A_GROUP_ID = "org.test";
- protected static final String MANIFEST_ONE_ARTIFACT_ID = "manifest-one";
- protected static final String MANIFEST_TWO_ARTIFACT_ID = "manifest-two";
- protected static final String A_VERSION = "1.2.3";
- @Mock
- public ResolvedArtifactsStore artifactVersions;
-
- @Mock
- public ManifestVersionResolver manifestVersionResolver;
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
- private File manifestFile;
- private ProsperoManifestVersionResolver resolver;
-
- @Before
- public void setUp() throws Exception {
- manifestFile = temp.newFile("test");
- Files.writeString(manifestFile.toPath(), ChannelManifestMapper.toYaml(
- new ChannelManifest("test", "test", "desc", null)));
-
- // when the fallback resolver is called return an empty record to make the test pass
- when(manifestVersionResolver.getCurrentVersions(any())).thenReturn(new ManifestVersionRecord());
-
- resolver = new ProsperoManifestVersionResolver(artifactVersions, manifestVersionResolver);
- }
-
- @Test
- public void versionResolvedDuringProvisioning() throws Exception {
- whenManifestOneWasResolveDuringProvisioning();
-
- final ManifestVersionRecord currentVersions = resolver.getCurrentVersions(List.of(new Channel.Builder()
- .setManifestCoordinate(new ChannelManifestCoordinate(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID))
- .build()));
-
- assertThat(currentVersions.getMavenManifests())
- .map(ManifestVersionRecord.MavenManifest::getVersion)
- .containsOnly(A_VERSION);
- assertThat(currentVersions.getMavenManifests())
- .map(ManifestVersionRecord.MavenManifest::getDescription)
- .containsOnly("desc");
- }
-
- @Test
- public void versionNotResolvedDuringProvisioning_FallsbackToMavenCache() throws Exception {
- when(artifactVersions.getManifestVersion(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID)).thenReturn(null);
-
- final List channels = List.of(new Channel.Builder()
- .setManifestCoordinate(new ChannelManifestCoordinate(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID))
- .build());
- resolver.getCurrentVersions(channels);
-
- verify(manifestVersionResolver).getCurrentVersions(channels);
- }
-
- @Test
- public void alreadyResolvedChannelsAreNotPassedThrough() throws Exception {
- whenManifestOneWasResolveDuringProvisioning();
-
- final List channels = List.of(
- new Channel.Builder()
- .setManifestCoordinate(new ChannelManifestCoordinate(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID))
- .build(),
- new Channel.Builder()
- .setManifestCoordinate(new ChannelManifestCoordinate(A_GROUP_ID, MANIFEST_TWO_ARTIFACT_ID))
- .build());
- resolver.getCurrentVersions(channels);
-
- verify(manifestVersionResolver).getCurrentVersions(List.of(channels.get(1)));
- }
-
- @Test
- public void nonOpenMavenChannelsAreResolvedWithFallback() throws Exception {
- whenManifestOneWasResolveDuringProvisioning();
-
- final List channels = List.of(
- new Channel.Builder()
- .setManifestCoordinate(new ChannelManifestCoordinate(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID, A_VERSION))
- .build(),
- new Channel.Builder()
- .setManifestUrl(new URI("http://test.te/manifest.yaml").toURL())
- .build());
- resolver.getCurrentVersions(channels);
-
- verify(manifestVersionResolver).getCurrentVersions(channels);
- }
-
- private void whenManifestOneWasResolveDuringProvisioning() {
- when(artifactVersions.getManifestVersion(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID)).thenReturn(
- new MavenArtifact(A_GROUP_ID, MANIFEST_ONE_ARTIFACT_ID, null, null, A_VERSION, manifestFile));
- }
-}
\ No newline at end of file
diff --git a/prospero-common/src/test/java/org/wildfly/prospero/galleon/ArtifactCacheTest.java b/prospero-common/src/test/java/org/wildfly/prospero/galleon/ArtifactCacheTest.java
index a77d658b0..999e39176 100644
--- a/prospero-common/src/test/java/org/wildfly/prospero/galleon/ArtifactCacheTest.java
+++ b/prospero-common/src/test/java/org/wildfly/prospero/galleon/ArtifactCacheTest.java
@@ -21,11 +21,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.wildfly.channel.ChannelManifest;
import org.wildfly.channel.MavenArtifact;
-import org.wildfly.prospero.metadata.ManifestVersionRecord;
-import org.wildfly.prospero.wfchannel.MavenSessionManager;
-import org.wildfly.prospero.wfchannel.ResolvedArtifactsStore;
import java.io.File;
import java.io.IOException;
@@ -38,8 +34,6 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class ArtifactCacheTest {
@@ -158,84 +152,6 @@ public void getArtifactDoesntReturnArtifactIfTheHashIsDifferent() throws Excepti
assertEquals(Optional.empty(), cachedArtifact);
}
- @Test
- public void cacheMavenManifests_ResolvedInList() throws Exception {
- final ManifestVersionRecord record = new ManifestVersionRecord();
- record.addManifest(new ManifestVersionRecord.MavenManifest("foo", "bar", "1.2.3", ""));
- final MavenSessionManager msm = mock(MavenSessionManager.class);
- final ResolvedArtifactsStore manifestVersions = mock(ResolvedArtifactsStore.class);
- when(msm.getResolvedArtifactVersions()).thenReturn(manifestVersions);
- final File testFile = temp.newFile("test");
- Files.writeString(testFile.toPath(), "test file");
- when(manifestVersions.getManifestVersion("foo", "bar")).thenReturn(
- new MavenArtifact("foo", "bar", null, null, "1.2.3", testFile));
-
- cache.cache(record, msm.getResolvedArtifactVersions());
-
- // verify the "test" file exists in cache
- final Optional cachedArtifact = cache.getArtifact("foo", "bar", ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, "1.2.3");
- assertThat(cachedArtifact.get())
- .hasSameBinaryContentAs(testFile);
- }
-
- @Test
- public void cacheMavenManifests_NotResolvedLocally() throws Exception {
- final ManifestVersionRecord record = new ManifestVersionRecord();
- record.addManifest(new ManifestVersionRecord.MavenManifest("foo", "bar", "1.2.3", ""));
- final MavenSessionManager msm = mock(MavenSessionManager.class);
- final ResolvedArtifactsStore manifestVersions = mock(ResolvedArtifactsStore.class);
- when(msm.getResolvedArtifactVersions()).thenReturn(manifestVersions);
- // the artifact is not found in resolved list
- when(manifestVersions.getManifestVersion("foo", "bar")).thenReturn(null);
-
- cache.cache(record, msm.getResolvedArtifactVersions());
-
- // verify the "test" file exists in cache
- final Optional cachedArtifact = cache.getArtifact("foo", "bar", ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, "1.2.3");
- assertThat(cachedArtifact)
- .isEmpty();
- }
-
- @Test
- public void cacheMavenManifests_ResolvedFileDoesNotExist() throws Exception {
- final ManifestVersionRecord record = new ManifestVersionRecord();
- record.addManifest(new ManifestVersionRecord.MavenManifest("foo", "bar", "1.2.3", ""));
- final MavenSessionManager msm = mock(MavenSessionManager.class);
- final ResolvedArtifactsStore manifestVersions = mock(ResolvedArtifactsStore.class);
- when(msm.getResolvedArtifactVersions()).thenReturn(manifestVersions);
- // the artifact is not found in resolved list
- when(manifestVersions.getManifestVersion("foo", "bar")).thenReturn(null);
-
- cache.cache(record, msm.getResolvedArtifactVersions());
-
- // verify the "test" file exists in cache
- final Optional cachedArtifact = cache.getArtifact("foo", "bar", ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, "1.2.3");
- assertThat(cachedArtifact)
- .isEmpty();
- }
-
- @Test
- public void cacheMavenManifests_ResolvedInListWithDifferentVersion() throws Exception {
- final ManifestVersionRecord record = new ManifestVersionRecord();
- record.addManifest(new ManifestVersionRecord.MavenManifest("foo", "bar", "1.2.3", ""));
- final MavenSessionManager msm = mock(MavenSessionManager.class);
- final ResolvedArtifactsStore manifestVersions = mock(ResolvedArtifactsStore.class);
- when(msm.getResolvedArtifactVersions()).thenReturn(manifestVersions);
- final File testFile = temp.newFile("test-1.2.3");
- Files.writeString(testFile.toPath(), "test file 1.2.3");
- final File testFile2 = temp.newFile("test-1.2.4");
- Files.writeString(testFile2.toPath(), "test file 1.2.4");
- when(manifestVersions.getManifestVersion("foo", "bar")).thenReturn(
- new MavenArtifact("foo", "bar", null, null, "1.2.4", testFile2));
-
- cache.cache(record, msm.getResolvedArtifactVersions());
-
- // verify the "test" file exists in cache
- final Optional cachedArtifact = cache.getArtifact("foo", "bar", ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, "1.2.3");
- assertThat(cachedArtifact)
- .isEmpty();
- }
-
@Test
public void cacheRecordsArtifactsInAlphabeticOrder() throws Exception {
cache.cache(otherArtifact);
diff --git a/prospero-common/src/test/java/org/wildfly/prospero/galleon/CachedVersionResolverTest.java b/prospero-common/src/test/java/org/wildfly/prospero/galleon/CachedVersionResolverTest.java
index ac89290c4..50fd49d77 100644
--- a/prospero-common/src/test/java/org/wildfly/prospero/galleon/CachedVersionResolverTest.java
+++ b/prospero-common/src/test/java/org/wildfly/prospero/galleon/CachedVersionResolverTest.java
@@ -94,7 +94,6 @@ public class CachedVersionResolverTest {
@Before
public void setUp() throws Exception {
- when(session.getRepositoryListener()).thenReturn(repositoryListener);
resolver = new CachedVersionResolver(mockResolver, artifactCache, system, session, manifestVersionProvider);
}
@@ -237,7 +236,6 @@ public void testResolveChannelMetadata_FallbackReturnsCachedFile() throws Except
assertThat(resolver.resolveChannelMetadata(List.of(new ChannelMetadataCoordinate("org.test", "manifest-one", ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION))))
.containsExactly(testFile.toURI().toURL());
- verify(repositoryListener).artifactResolved(any());
}
@Test
@@ -260,7 +258,6 @@ public void testResolveChannelMetadata_FallbackReturnsCachedFile_WithTwoManifest
new ChannelMetadataCoordinate("org.test", "manifest-one", ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION),
new ChannelMetadataCoordinate("org.test", "manifest-two", ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION))))
.containsExactly(testFileOne.toURI().toURL(), testFileTwo.toURI().toURL());
- verify(repositoryListener, times(2)).artifactResolved(any());
}
@Test
@@ -288,7 +285,5 @@ public void testResolveChannelMetadata_OneManifestResolvedNormally() throws Exce
new ChannelManifestCoordinate("org.test", "manifest-one"),
new ChannelManifestCoordinate("org.test", "manifest-two"))))
.containsExactly(testFileOne.toURI().toURL(), testFileTwo.toURI().toURL());
- // only called on the cached artifact
- verify(repositoryListener).artifactResolved(any());
}
}
\ No newline at end of file
diff --git a/prospero-common/src/test/java/org/wildfly/prospero/spi/ProsperoInstallationManagerTest.java b/prospero-common/src/test/java/org/wildfly/prospero/spi/ProsperoInstallationManagerTest.java
index dc08526dc..408e2c618 100644
--- a/prospero-common/src/test/java/org/wildfly/prospero/spi/ProsperoInstallationManagerTest.java
+++ b/prospero-common/src/test/java/org/wildfly/prospero/spi/ProsperoInstallationManagerTest.java
@@ -26,8 +26,11 @@
import org.wildfly.channel.Channel;
import org.wildfly.channel.ChannelManifestCoordinate;
import org.wildfly.channel.Repository;
+import org.wildfly.installationmanager.CandidateType;
+import org.wildfly.installationmanager.FileConflict;
import org.wildfly.installationmanager.InstallationChanges;
import org.wildfly.installationmanager.MavenOptions;
+import org.wildfly.prospero.actions.ApplyCandidateAction;
import org.wildfly.prospero.actions.InstallationHistoryAction;
import org.wildfly.prospero.actions.UpdateAction;
import org.wildfly.prospero.api.ChannelChange;
@@ -35,9 +38,12 @@
import org.wildfly.prospero.updates.UpdateSet;
import java.nio.file.Path;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -66,6 +72,9 @@ public class ProsperoInstallationManagerTest {
@Mock
private InstallationHistoryAction historyAction;
+ @Mock
+ private ApplyCandidateAction applyCandidateAction;
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -245,4 +254,37 @@ public void mapMavenOptions() throws Exception {
assertTrue(mavenOptions.isNoLocalCache());
assertNull(mavenOptions.getLocalCache());
}
+
+ @Test
+ public void testCheckUpdatesMapsConflicts() throws Exception {
+ final ProsperoInstallationManager mgr = new ProsperoInstallationManager(actionFactory);
+
+ when(actionFactory.getApplyCandidateAction(any())).thenReturn(applyCandidateAction);
+ when(applyCandidateAction.verifyCandidate(any())).thenReturn(ApplyCandidateAction.ValidationResult.OK);
+ when(applyCandidateAction.getConflicts()).thenReturn(List.of(
+ org.wildfly.prospero.api.FileConflict.userModified("foo/bar").updateModified().userPreserved(),
+ org.wildfly.prospero.api.FileConflict.userModified("system/file_a").updateModified().overwritten(),
+ org.wildfly.prospero.api.FileConflict.userAdded("system/file_b").updateAdded().overwritten()
+ ));
+
+ final Collection conflicts = mgr.verifyCandidate(Path.of("candidate"), CandidateType.UPDATE);
+ assertThat(conflicts)
+ .contains(
+ new FileConflict(Path.of("foo/bar"), FileConflict.Status.MODIFIED, FileConflict.Status.MODIFIED, false),
+ new FileConflict(Path.of("system/file_a"), FileConflict.Status.MODIFIED, FileConflict.Status.MODIFIED, true),
+ new FileConflict(Path.of("system/file_b"), FileConflict.Status.ADDED, FileConflict.Status.ADDED, true)
+ );
+ }
+
+ @Test
+ public void testCheckUpdatesThrowsVerificationExceptions() throws Exception {
+ final ProsperoInstallationManager mgr = new ProsperoInstallationManager(actionFactory);
+
+ when(actionFactory.getApplyCandidateAction(any())).thenReturn(applyCandidateAction);
+ when(applyCandidateAction.verifyCandidate(any())).thenReturn(ApplyCandidateAction.ValidationResult.STALE);
+
+ assertThatThrownBy(() -> mgr.verifyCandidate(Path.of("candidate"), CandidateType.UPDATE))
+ .hasMessageContaining("has been modified after the candidate has been created");
+
+ }
}
\ No newline at end of file
diff --git a/prospero-common/src/test/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListenerTest.java b/prospero-common/src/test/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListenerTest.java
deleted file mode 100644
index dc9f0d56b..000000000
--- a/prospero-common/src/test/java/org/wildfly/prospero/wfchannel/ProsperoMavenRepositoryListenerTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2024 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.wildfly.prospero.wfchannel;
-
-import org.eclipse.aether.RepositoryEvent;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.DefaultArtifact;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.wildfly.channel.ChannelManifest;
-import org.wildfly.channel.MavenArtifact;
-
-import java.io.File;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@RunWith(MockitoJUnitRunner.class)
-public class ProsperoMavenRepositoryListenerTest {
-
- protected static final String A_GROUP = "org.test";
- protected static final String AN_ARTIFACT = "artifact-one";
- protected static final String A_VERSION = "1.2.3";
- @Mock
- private RepositorySystemSession session;
- private ProsperoMavenRepositoryListener listener;
- private File testFile;
-
- @Before
- public void setUp() {
-
- listener = new ProsperoMavenRepositoryListener();
- testFile = new File("test");
- }
-
- @Test
- public void testRecordArtifact() throws Exception {
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(resolvedArtifact(testFile))
- .build());
-
- assertThat(listener.getManifestVersion(A_GROUP, AN_ARTIFACT))
- .isEqualTo(new MavenArtifact(A_GROUP, AN_ARTIFACT,
- ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, A_VERSION, testFile));
-
- }
-
- @Test
- public void testDontRecordArtifactWithoutFile() throws Exception {
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(resolvedArtifact(null))
- .build());
-
- assertThat(listener.getManifestVersion(A_GROUP, AN_ARTIFACT))
- .isNull();
- }
-
- @Test
- public void testDontRecordArtifactWhenEventDoesntHaveArtifact() throws Exception {
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .build());
-
- assertThat(listener.getManifestVersion(A_GROUP, AN_ARTIFACT))
- .isNull();
- }
-
- @Test
- public void testReturnNullIfArtifactHasntBeenResolved() throws Exception {
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(resolvedArtifact(testFile))
- .build());
-
- assertThat(listener.getManifestVersion(A_GROUP, "idont-exist"))
- .isNull();
- }
-
- @Test
- public void resolvingSameArtifactTwiceReplacesArtifact() throws Exception {
- final File testFileTwo = new File("test-two");
-
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(resolvedArtifact(testFile))
- .build());
- listener.artifactResolved(new RepositoryEvent.Builder(session, RepositoryEvent.EventType.ARTIFACT_RESOLVED)
- .setArtifact(resolvedArtifact(testFileTwo))
- .build());
-
- assertThat(listener.getManifestVersion(A_GROUP, AN_ARTIFACT))
- .isEqualTo(new MavenArtifact(A_GROUP, AN_ARTIFACT,
- ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, A_VERSION, testFileTwo));
- }
-
- private DefaultArtifact resolvedArtifact(File testFile) {
- if (testFile == null) {
- return new DefaultArtifact(A_GROUP, AN_ARTIFACT,
- ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION, A_VERSION);
- } else {
- return new DefaultArtifact(A_GROUP, AN_ARTIFACT,
- ChannelManifest.CLASSIFIER, ChannelManifest.EXTENSION, A_VERSION,
- null, testFile);
- }
- }
-}
\ No newline at end of file