/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.patching.runner;
import static org.jboss.as.patching.HashUtils.hashFile;
import static org.jboss.as.patching.IoUtils.mkdir;
import static org.jboss.as.patching.IoUtils.newFile;
import static org.jboss.as.patching.Constants.BASE;
import static org.jboss.as.patching.runner.PatchingAssert.assertDefinedModule;
import static org.jboss.as.patching.runner.PatchingAssert.assertDirDoesNotExist;
import static org.jboss.as.patching.runner.PatchingAssert.assertDirExists;
import static org.jboss.as.patching.runner.PatchingAssert.assertFileContent;
import static org.jboss.as.patching.runner.PatchingAssert.assertFileExists;
import static org.jboss.as.patching.runner.PatchingAssert.assertPatchHasBeenApplied;
import static org.jboss.as.patching.runner.PatchingAssert.assertPatchHasBeenRolledBack;
import static org.jboss.as.patching.runner.TestUtils.createPatchXMLFile;
import static org.jboss.as.patching.runner.TestUtils.createZippedPatchFile;
import static org.jboss.as.patching.runner.TestUtils.dump;
import static org.jboss.as.patching.runner.TestUtils.randomString;
import static org.jboss.as.patching.runner.TestUtils.touch;
import static org.jboss.as.patching.runner.TestUtils.tree;
import java.io.File;
import org.jboss.as.patching.installation.Identity;
import org.jboss.as.patching.installation.InstalledIdentity;
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.patching.tool.PatchingResult;
import org.jboss.as.version.ProductConfig;
import org.junit.Test;
/**
* @author <a href="http://jmesnil.net/">Jeff Mesnil</a> (c) 2012, Red Hat Inc
*/
public class CumulativePatchTestCase extends AbstractTaskTestCase {
@Test
public void testApplyReleasePatch() throws Exception {
// build a Release patch for the base installation
// with 1 added module
String patchID = randomString();
String layerPatchID = randomString();
File patchDir = mkdir(tempDir, patchID);
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(patchDir, layerPatchID, moduleName);
InstalledIdentity installedIdentity = loadInstalledIdentity();
Patch patch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription(randomString())
.upgradeIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion(), productConfig.getProductVersion() + "-Release1")
.getParent()
.upgradeElement(layerPatchID, BASE, false)
.addContentModification(moduleAdded)
.getParent()
.build();
createPatchXMLFile(patchDir, patch);
File zippedPatch = createZippedPatchFile(patchDir, patchID);
PatchingResult result = executePatch(zippedPatch);
assertPatchHasBeenApplied(result, patch);
InstalledIdentity updatedInstalledIdentity = loadInstalledIdentity();
File modulePatchDirectory = updatedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAdded.getItem().getContentHash());
}
@Test
public void testApplyReleasePatchAndRollback() throws Exception {
// start from a base installation
// create an existing file in the AS7 installation
File binDir = mkdir(env.getInstalledImage().getJbossHome(), "bin");
String fileName = "standalone.sh";
File standaloneShellFile = touch(binDir, fileName);
dump(standaloneShellFile, "original script to run standalone AS7");
byte[] existingHash = hashFile(standaloneShellFile);
// build a Release patch for the base installation
// with 1 added module
// and 1 updated file
String patchID = randomString();
String layerPatchID = randomString();
File patchDir = mkdir(tempDir, patchID);
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(patchDir, layerPatchID, moduleName);
ContentModification fileModified = ContentModificationUtils.modifyMisc(patchDir, patchID, "updated script", standaloneShellFile, "bin", "standalone.sh");
InstalledIdentity installedIdentity = loadInstalledIdentity();
Patch patch = PatchBuilder.create()
.setPatchId(patchID)
.setDescription(randomString())
.upgradeIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion(), productConfig.getProductVersion() + "-Release1")
.getParent()
.upgradeElement(layerPatchID, BASE, false)
.addContentModification(moduleAdded)
.getParent()
.addContentModification(fileModified)
.build();
createPatchXMLFile(patchDir, patch);
File zippedPatch = createZippedPatchFile(patchDir, patchID);
Identity identityBeforePatch = loadInstalledIdentity().getIdentity();
PatchingResult result = executePatch(zippedPatch);
assertPatchHasBeenApplied(result, patch);
assertFileExists(standaloneShellFile);
assertFileContent(fileModified.getItem().getContentHash(), standaloneShellFile);
InstalledIdentity updatedInstalledIdentity = loadInstalledIdentity();
File modulePatchDirectory = updatedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAdded.getItem().getContentHash());
// rollback the patch based on the updated PatchInfo
PatchingResult rollbackResult = rollback(patchID);
tree(env.getInstalledImage().getJbossHome());
assertPatchHasBeenRolledBack(rollbackResult, identityBeforePatch);
assertFileExists(standaloneShellFile);
assertFileContent(existingHash, standaloneShellFile);
}
@Test
public void testApplyReleasePatchThenOneOffPatch() throws Exception {
// build a Release patch for the base installation
// with 1 added module
String releasePatchID = randomString();
String releaseLayerPatchID = randomString();
File releasePatchDir = mkdir(tempDir, releasePatchID);
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(releasePatchDir, releaseLayerPatchID, moduleName);
InstalledIdentity installedIdentity = loadInstalledIdentity();
final String resultingVersion = productConfig.getProductVersion() + "-Release1";
Patch releasePatch = PatchBuilder.create()
.setPatchId(releasePatchID)
.setDescription(randomString())
.upgradeIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion(), resultingVersion)
.getParent()
.upgradeElement(releaseLayerPatchID, BASE, false)
.addContentModification(moduleAdded)
.getParent()
.build();
createPatchXMLFile(releasePatchDir, releasePatch);
File zippedReleasePatch = createZippedPatchFile(releasePatchDir, releasePatchID);
PatchingResult resultOfReleasePatch = executePatch(zippedReleasePatch);
assertPatchHasBeenApplied(resultOfReleasePatch, releasePatch);
// FIXME when is the product version persisted when the release is applied?
productConfig = new ProductConfig(productConfig.getProductName(), productConfig.getProductVersion() + "-Release1", productConfig.getConsoleSlot());
InstalledIdentity updatedInstalledIdentity = loadInstalledIdentity();
File modulePatchDirectory = updatedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(releaseLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAdded.getItem().getContentHash());
// apply a one-off patch now
String oneOffPatchID = randomString();
String oneOffLayerPatchID = randomString();
File oneOffPatchDir = mkdir(tempDir, oneOffPatchID);
ContentModification moduleModified = ContentModificationUtils.modifyModule(oneOffPatchDir, oneOffLayerPatchID, newFile(modulePatchDirectory, moduleName), "new resource in the module");
Patch oneOffPatch = PatchBuilder.create()
.setPatchId(oneOffPatchID)
.setDescription(randomString())
// one-off patch can be applied to Release
.oneOffPatchIdentity(productConfig.getProductName(), resultingVersion)
.getParent()
.oneOffPatchElement(oneOffLayerPatchID, BASE, false)
.addContentModification(moduleModified)
.getParent()
.build();
createPatchXMLFile(oneOffPatchDir, oneOffPatch);
File zippedOneOffPatch = createZippedPatchFile(oneOffPatchDir, oneOffPatchID);
PatchingResult resultOfOneOffPatch = executePatch(zippedOneOffPatch);
assertPatchHasBeenApplied(resultOfOneOffPatch, oneOffPatch);
InstalledIdentity installedIdentityAfterOneOffPatch = loadInstalledIdentity();
modulePatchDirectory = installedIdentityAfterOneOffPatch.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(oneOffLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleModified.getItem().getContentHash());
}
@Test
public void testApplyReleasePatchThenOneOffPatchThenRollbackReleasePatch() throws Exception {
// build a Release patch for the base installation
// with 1 added module
String releasePatchID = randomString();
String releaseLayerPatchID = randomString();
File releasePatchDir = mkdir(tempDir, releasePatchID);
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(releasePatchDir, releaseLayerPatchID, moduleName);
InstalledIdentity identityBeforePatch = loadInstalledIdentity();
final String resultingVersion = identityBeforePatch.getIdentity().getVersion() + "-Release1";
Patch releasePatch = PatchBuilder.create()
.setPatchId(releasePatchID)
.setDescription(randomString())
.upgradeIdentity(identityBeforePatch.getIdentity().getName(), identityBeforePatch.getIdentity().getVersion(), resultingVersion)
.getParent()
.upgradeElement(releaseLayerPatchID, BASE, false)
.addContentModification(moduleAdded)
.getParent()
.build();
createPatchXMLFile(releasePatchDir, releasePatch);
File zippedReleasePatch = createZippedPatchFile(releasePatchDir, releasePatchID);
PatchingResult resultOfReleasePatch = executePatch(zippedReleasePatch);
assertPatchHasBeenApplied(resultOfReleasePatch, releasePatch);
// FIXME when is the product version persisted when the release is applied?
productConfig = new ProductConfig(productConfig.getProductName(), productConfig.getProductVersion() + "-Release1", productConfig.getConsoleSlot());
InstalledIdentity updatedInstalledIdentity = loadInstalledIdentity();
File modulePatchDirectory = updatedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(releaseLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAdded.getItem().getContentHash());
// apply a one-off patch now
String oneOffPatchID = randomString();
String oneOffLayerPatchID = randomString();
File oneOffPatchDir = mkdir(tempDir, oneOffPatchID);
ContentModification moduleModified = ContentModificationUtils.modifyModule(oneOffPatchDir, oneOffLayerPatchID, newFile(modulePatchDirectory, moduleName), "new resource in the module");
Patch oneOffPatch = PatchBuilder.create()
.setPatchId(oneOffPatchID)
.setDescription(randomString())
// one-off patch can be applied to Release
.oneOffPatchIdentity(productConfig.getProductName(), resultingVersion)
.getParent()
.oneOffPatchElement(oneOffLayerPatchID, BASE, false)
.addContentModification(moduleModified)
.getParent()
.build();
createPatchXMLFile(oneOffPatchDir, oneOffPatch);
File zippedOneOffPatch = createZippedPatchFile(oneOffPatchDir, oneOffPatchID);
PatchingResult resultOfOneOffPatch = executePatch(zippedOneOffPatch);
assertPatchHasBeenApplied(resultOfOneOffPatch, oneOffPatch);
InstalledIdentity installedIdentityAfterOneOffPatch = loadInstalledIdentity();
modulePatchDirectory = installedIdentityAfterOneOffPatch.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(oneOffLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleModified.getItem().getContentHash());
// rollback the release patch, this should also rollback the one-off patch
PatchingResult resultOfReleasePatchRollback = rollback(releasePatchID);
tree(env.getInstalledImage().getJbossHome());
assertPatchHasBeenRolledBack(resultOfReleasePatchRollback, identityBeforePatch.getIdentity());
updatedInstalledIdentity = loadInstalledIdentity();
File layerModuleRoot = updatedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModuleRoot();
assertDirDoesNotExist(newFile(layerModuleRoot, moduleName));
}
@Test
public void testInvalidateOneOffPatches() throws Exception {
// build a one-off patch for the base installation
// with 1 added module
String oneOffPatchID = "oneOffPatchID";//randomString();
String oneOffLayerPatchID = "oneOffLayerPatchID";//randomString();
File oneOffPatchDir = mkdir(tempDir, oneOffPatchID);
String moduleName = "mymodule";//randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(oneOffPatchDir, oneOffLayerPatchID, moduleName);
InstalledIdentity identityBeforePatch = loadInstalledIdentity();
Patch oneOffPatch = PatchBuilder.create()
.setPatchId(oneOffPatchID)
.setDescription(randomString())
// one-off patch can be applied to Release
.oneOffPatchIdentity(productConfig.getProductName(), productConfig.getProductVersion())
.getParent()
.oneOffPatchElement(oneOffLayerPatchID, BASE, false)
.addContentModification(moduleAdded)
.getParent()
.build();
createPatchXMLFile(oneOffPatchDir, oneOffPatch);
File zippedOneOffPatch = createZippedPatchFile(oneOffPatchDir, oneOffPatchID);
PatchingResult resultOfOneOffPatch = executePatch(zippedOneOffPatch);
assertPatchHasBeenApplied(resultOfOneOffPatch, oneOffPatch);
InstalledIdentity installedIdentityAfterOneOffPatch = loadInstalledIdentity();
File modulePatchDirectory = installedIdentityAfterOneOffPatch.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(oneOffLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAdded.getItem().getContentHash());
// build a Release patch for the base installation
String releasePatchID = "releasePatchID";// randomString() + "-Release";
String releaseLayerPatchID = "releaseLayerPatchID";//randomString();
File releasePatchDir = mkdir(tempDir, releasePatchID);
ContentModification moduleAddedInReleasePatch = ContentModificationUtils.addModule(releasePatchDir, releaseLayerPatchID, moduleName, "different content in the module");
final String resultingVersion = identityBeforePatch.getIdentity().getVersion() + "-Release1";
Patch releasePatch = PatchBuilder.create()
.setPatchId(releasePatchID)
.setDescription(randomString())
.upgradeIdentity(identityBeforePatch.getIdentity().getName(), identityBeforePatch.getIdentity().getVersion(), resultingVersion)
.getParent()
.upgradeElement(releaseLayerPatchID, BASE, false)
.addContentModification(moduleAddedInReleasePatch)
.getParent()
.build();
createPatchXMLFile(releasePatchDir, releasePatch);
File zippedReleasePatch = createZippedPatchFile(releasePatchDir, releasePatchID);
PatchingResult resultOfReleasePatch = executePatch(zippedReleasePatch);
assertPatchHasBeenApplied(resultOfReleasePatch, releasePatch);
tree(env.getInstalledImage().getJbossHome());
modulePatchDirectory = installedIdentityAfterOneOffPatch.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(releaseLayerPatchID);
assertDirExists(modulePatchDirectory);
assertDefinedModule(modulePatchDirectory, moduleName, moduleAddedInReleasePatch.getItem().getContentHash());
}
}