package org.jboss.as.test.patching;
import static org.jboss.as.patching.IoUtils.mkdir;
import static org.jboss.as.patching.IoUtils.newFile;
import static org.jboss.as.test.patching.PatchingTestUtil.AS_DISTRIBUTION;
import static org.jboss.as.test.patching.PatchingTestUtil.AS_VERSION;
import static org.jboss.as.test.patching.PatchingTestUtil.FILE_SEPARATOR;
import static org.jboss.as.test.patching.PatchingTestUtil.MODULES_PATH;
import static org.jboss.as.test.patching.PatchingTestUtil.PRODUCT;
import static org.jboss.as.test.patching.PatchingTestUtil.createPatchBundleXMLFile;
import static org.jboss.as.test.patching.PatchingTestUtil.createPatchXMLFile;
import static org.jboss.as.test.patching.PatchingTestUtil.createZippedPatchFile;
import static org.jboss.as.test.patching.PatchingTestUtil.randomString;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.jboss.as.patching.Constants;
import org.jboss.as.patching.HashUtils;
import org.jboss.as.patching.metadata.BundledPatch;
import org.jboss.as.patching.metadata.ContentModification;
import org.jboss.as.patching.metadata.Patch;
import org.jboss.as.patching.metadata.PatchBuilder;
import org.jboss.as.test.patching.util.module.Module;
import org.jboss.as.version.ProductConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.wildfly.core.testrunner.ServerControl;
import org.wildfly.core.testrunner.WildflyTestRunner;
/**
* @author Martin Simka
*/
@RunWith(WildflyTestRunner.class)
@ServerControl(manual = true)
public class PatchBundleTestCase extends AbstractPatchingTestCase {
/**
* creates 4 CPs
* creates bundle containing 4 CPs
* applies bundle
* rollbacks CP one by one
*
* @throws Exception
*/
@Test
public void testApplyBundle() throws Exception {
final String bundleName = "bundle_" + randomString();
File patchBundleDir = mkdir(tempDir, bundleName);
final String cpPatchID = randomString();
final String cpPatchID2 = randomString();
final String cpPatchID3 = randomString();
final String cpPatchID4 = randomString();
final String eapWithCP = "EAP with cp patch";
final String eapWithCP2 = "EAP with cp patch 2";
final String eapWithCP3 = "EAP with cp patch 3";
final String eapWithCP4 = "EAP with cp patch 4";
List<BundledPatch.BundledPatchEntry> patches = new ArrayList<BundledPatch.BundledPatchEntry>();
File cpZip = createCumulativePatchAddingARandomModule(cpPatchID, AS_VERSION, eapWithCP, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID, cpZip.getName()));
File cpZip2 = createNextCumulativePatchAddingRandomModule(cpPatchID2, eapWithCP, cpPatchID, eapWithCP2, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID2, cpZip2.getName()));
File cpZip3 = createNextCumulativePatchModyfyingJbossModules(cpPatchID3, eapWithCP2, cpPatchID2, eapWithCP3, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID3, cpZip3.getName()));
File cpZip4 = createNextCumulativePatchAddingRandomModule(cpPatchID4, eapWithCP3, cpPatchID3, eapWithCP4, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID4, cpZip4.getName()));
createPatchBundleXMLFile(patchBundleDir, patches);
File patchBundleZip = createZippedPatchFile(patchBundleDir, bundleName);
// apply bundle
controller.start();
Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(patchBundleZip.getAbsolutePath()));
Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp version and rollback cp4
controller.start();
Assert.assertTrue("The patch " + cpPatchID4 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID4));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp version and rollback cp4
controller.start();
Assert.assertTrue("The patch " + cpPatchID3 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID3));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp version and rollback cp2
controller.start();
Assert.assertTrue("The patch " + cpPatchID2 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID2));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp version and rollback cp
controller.start();
Assert.assertTrue("The patch " + cpPatchID + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify base
controller.start();
Assert.assertTrue("The patch " + Constants.BASE + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(Constants.BASE));
controller.stop();
}
/**
* creates 4 CPs
* creates bundle containing 4 CPs
* applies CP1
* applies CP2
* applies one-off
* applies bundle
* rollbacks CPs and one-off one by one
*
* @throws Exception
*/
@Test
public void testApplyBundleSkipTwoCPs() throws Exception {
final String bundleName = "bundle_" + randomString();
File patchBundleDir = mkdir(tempDir, bundleName);
final String cpPatchID = randomString();
final String cpPatchID2 = randomString();
final String cpPatchID3 = randomString();
final String cpPatchID4 = randomString();
final String oneOffId = randomString();
final String eapWithCP = "EAP with cp patch";
final String eapWithCP2 = "EAP with cp patch 2";
final String eapWithCP3 = "EAP with cp patch 3";
final String eapWithCP4 = "EAP with cp patch 4";
List<BundledPatch.BundledPatchEntry> patches = new ArrayList<BundledPatch.BundledPatchEntry>();
File cpZip = createCumulativePatchAddingARandomModule(cpPatchID, AS_VERSION, eapWithCP, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID, cpZip.getName()));
File cpZip2 = createNextCumulativePatchAddingRandomModule(cpPatchID2, eapWithCP, cpPatchID, eapWithCP2, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID2, cpZip2.getName()));
File cpZip3 = createNextCumulativePatchModyfyingJbossModules(cpPatchID3, eapWithCP2, cpPatchID2, eapWithCP3, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID3, cpZip3.getName()));
File cpZip4 = createNextCumulativePatchAddingRandomModule(cpPatchID4, eapWithCP3, cpPatchID3, eapWithCP4, patchBundleDir);
patches.add(new BundledPatch.BundledPatchEntry(cpPatchID4, cpZip4.getName()));
File oneOffZip = createOneOffPatchAddingMiscFile(oneOffId, eapWithCP2);
createPatchBundleXMLFile(patchBundleDir, patches);
File patchBundleZip = createZippedPatchFile(patchBundleDir, bundleName);
// apply cp1
controller.start();
Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(cpZip.getAbsolutePath()));
Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and apply cp2
controller.start();
Assert.assertTrue("The patch " + cpPatchID + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID));
Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(cpZip2.getAbsolutePath()));
Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and apply oneoff
controller.start();
Assert.assertTrue("The patch " + cpPatchID2 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID2));
Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(oneOffZip.getAbsolutePath()));
Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and oneoff and apply bundle
controller.start();
Assert.assertTrue("The patch " + cpPatchID2 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID2));
Assert.assertTrue("The patch " + oneOffId + " should be listed as installed",
CliUtilsForPatching.getInstalledPatches().contains(oneOffId));
Assert.assertTrue("Patch should be accepted", CliUtilsForPatching.applyPatch(patchBundleZip.getAbsolutePath()));
Assert.assertTrue("server should be in restart-required mode", CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and rollback cp4
controller.start();
Assert.assertTrue("The patch " + cpPatchID4 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID4));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and rollback cp3
controller.start();
Assert.assertTrue("The patch " + cpPatchID3 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID3));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and rollback oneoff
controller.start();
Assert.assertTrue("The patch " + cpPatchID2 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID2));
Assert.assertTrue("The patch " + oneOffId + " should be listed as installed",
CliUtilsForPatching.getInstalledPatches().contains(oneOffId));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackPatch(oneOffId));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and rollback cp2
controller.start();
Assert.assertTrue("The patch " + cpPatchID2 + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID2));
Assert.assertFalse("The patch " + oneOffId + " should not be listed as installed",
CliUtilsForPatching.getInstalledPatches().contains(oneOffId));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify cp and rollback cp
controller.start();
Assert.assertTrue("The patch " + cpPatchID + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(cpPatchID));
Assert.assertTrue("Rollback should be accepted", CliUtilsForPatching.rollbackCumulativePatch(true));
Assert.assertTrue("server should be in restart-required mode",
CliUtilsForPatching.doesServerRequireRestart());
controller.stop();
// verify base
controller.start();
Assert.assertTrue("The patch " + Constants.BASE + " should be listed as installed",
CliUtilsForPatching.getCumulativePatchId().equalsIgnoreCase(Constants.BASE));
controller.stop();
}
private File createCumulativePatchAddingARandomModule(String patchID, String asVersion, final String targetAsVersion, File targetDir) throws Exception {
String layerPatchID = "layer" + patchID;
File cpPatchDir = mkdir(tempDir, patchID);
final String moduleName = "org.wildfly.test." + randomString();
final ResourceItem resourceItem1 = new ResourceItem("testFile1", "content1".getBytes(StandardCharsets.UTF_8));
final ResourceItem resourceItem2 = new ResourceItem("testFile2", "content2".getBytes(StandardCharsets.UTF_8));
Module newModule = new Module.Builder(moduleName)
.miscFile(resourceItem1)
.miscFile(resourceItem2)
.build();
// Create the version module
final String versionModuleName = ProductInfo.getVersionModule();
final String slot = ProductInfo.getVersionModuleSlot();
final String originalVersionModulePath = MODULES_PATH + FILE_SEPARATOR + versionModuleName.replace(".", FILE_SEPARATOR) + FILE_SEPARATOR + slot;
final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion);
ContentModification moduleAdded = ContentModificationUtils.addModule(cpPatchDir, layerPatchID, newModule);
ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchID, HashUtils.hashFile(new File(originalVersionModulePath)), modifiedModule);
Patch cpPatch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription("A cp patch.")
.upgradeIdentity(PRODUCT, asVersion, targetAsVersion)
.getParent()
.upgradeElement(layerPatchID, "base", false)
.addContentModification(moduleAdded)
.addContentModification(versionModuleModified)
.getParent()
.build();
createPatchXMLFile(cpPatchDir, cpPatch);
return createZippedPatchFile(cpPatchDir, patchID, targetDir);
}
private File createNextCumulativePatchAddingRandomModule(String patchID, String asVersion, final String currentPatch, final String targetAsVersion, File targetDir) throws Exception {
String layerPatchID = "layer" + patchID;
File cpPatchDir = mkdir(tempDir, patchID);
final String moduleName = "org.wildfly.test." + randomString();
// Create the version module
final String versionModuleName = ProductInfo.getVersionModule();
final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion);
// Calculate the target hash of the currently active module
final String currentLayerPatchID = "layer" + currentPatch;
File originalVersionModulePath = new File(tempDir, currentPatch);
originalVersionModulePath = new File(originalVersionModulePath, currentLayerPatchID);
originalVersionModulePath = new File(originalVersionModulePath, Constants.MODULES);
originalVersionModulePath = newFile(originalVersionModulePath, versionModuleName.split("\\."));
originalVersionModulePath = new File(originalVersionModulePath, ProductInfo.getVersionModuleSlot());
byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath);
assert patchedAsVersionHash != null;
final ResourceItem resourceItem1 = new ResourceItem("testFile1", "content1".getBytes(StandardCharsets.UTF_8));
final ResourceItem resourceItem2 = new ResourceItem("testFile2", "content2".getBytes(StandardCharsets.UTF_8));
Module newModule = new Module.Builder(moduleName)
.miscFile(resourceItem1)
.miscFile(resourceItem2)
.build();
ContentModification moduleAdded = ContentModificationUtils.addModule(cpPatchDir, layerPatchID, newModule);
ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchID, patchedAsVersionHash, modifiedModule);
ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main");
Patch cpPatch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription("A cp patch.")
.upgradeIdentity(productConfig.getProductName(), productConfig.getProductVersion(), targetAsVersion)
.getParent()
.upgradeElement(layerPatchID, "base", false)
.addContentModification(versionModuleModified)
.addContentModification(moduleAdded)
.getParent()
.build();
createPatchXMLFile(cpPatchDir, cpPatch);
return createZippedPatchFile(cpPatchDir, patchID, targetDir);
}
private File createNextCumulativePatchModyfyingJbossModules(String patchID, String asVersion, final String currentPatch, final String targetAsVersion, File targetDir) throws Exception {
String layerPatchID = "layer" + patchID;
File cpPatchDir = mkdir(tempDir, patchID);
// Also see if we can update jboss-modules
final File installation = new File(AS_DISTRIBUTION);
final File patchDir = new File(cpPatchDir, patchID);
final ContentModification jbossModulesModification = PatchingTestUtil.updateModulesJar(installation, patchDir);
// Create the version module
final String versionModuleName = ProductInfo.getVersionModule();
final Module modifiedModule = PatchingTestUtil.createVersionModule(targetAsVersion);
// Calculate the target hash of the currently active module
final String currentLayerPatchID = "layer" + currentPatch;
File originalVersionModulePath = new File(tempDir, currentPatch);
originalVersionModulePath = new File(originalVersionModulePath, currentLayerPatchID);
originalVersionModulePath = new File(originalVersionModulePath, Constants.MODULES);
originalVersionModulePath = newFile(originalVersionModulePath, versionModuleName.split("\\."));
originalVersionModulePath = new File(originalVersionModulePath, ProductInfo.getVersionModuleSlot());
byte[] patchedAsVersionHash = HashUtils.hashFile(originalVersionModulePath);
assert patchedAsVersionHash != null;
ContentModification versionModuleModified = ContentModificationUtils.modifyModule(cpPatchDir, layerPatchID, patchedAsVersionHash, modifiedModule);
Patch cpPatch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription("A cp patch.")
.upgradeIdentity(PRODUCT, asVersion, targetAsVersion)
.getParent()
.upgradeElement(layerPatchID, "base", false)
.addContentModification(versionModuleModified)
.getParent()
.addContentModification(jbossModulesModification)
.build();
createPatchXMLFile(cpPatchDir, cpPatch);
return createZippedPatchFile(cpPatchDir, patchID, targetDir);
}
private File createOneOffPatchAddingMiscFile(String patchID, String asVersion) throws Exception {
File oneOffPatchDir = mkdir(tempDir, patchID);
ContentModification miscFileAdded = ContentModificationUtils.addMisc(oneOffPatchDir, patchID,
"test content", "awesomeDirectory", "awesomeFile");
ProductConfig productConfig = new ProductConfig(PRODUCT, asVersion, "main");
Patch oneOffPatch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription("A one-off patch adding a misc file.")
.oneOffPatchIdentity(productConfig.getProductName(), productConfig.getProductVersion())
.getParent()
.addContentModification(miscFileAdded)
.build();
createPatchXMLFile(oneOffPatchDir, oneOffPatch);
return createZippedPatchFile(oneOffPatchDir, patchID);
}
}