/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, 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.installation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.jboss.as.patching.Constants.BASE;
import static org.jboss.as.patching.IoUtils.mkdir;
import static org.jboss.as.patching.IoUtils.newFile;
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.assertFileExists;
import static org.jboss.as.patching.runner.PatchingAssert.assertInstallationIsPatched;
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.randomString;
import static org.junit.Assert.fail;
import java.io.File;
import java.util.List;
import org.jboss.as.patching.DirectoryStructure;
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.runner.AbstractTaskTestCase;
import org.jboss.as.patching.runner.ContentModificationUtils;
import org.jboss.as.patching.runner.PatchingAssert;
import org.jboss.as.patching.runner.TestUtils;
import org.jboss.as.patching.tool.PatchingResult;
import org.junit.Test;
/**
* @author <a href="http://jmesnil.net/">Jeff Mesnil</a> (c) 2013 Red Hat inc.
*/
public class LayerTestCase extends AbstractTaskTestCase {
@Test
public void layerNotInLayersConf() throws Exception {
String layerName = randomString();
installLayers(false, layerName);
InstalledIdentity installedIdentity = loadInstalledIdentity();
// if the layer name is not in layers.conf, it's not part of the installed identity
List<Layer> layers = installedIdentity.getLayers();
assertEquals(1, layers.size());
assertEquals(BASE, layers.get(0).getName()); // only the base layer is installled
}
@Test
public void installedLayer() throws Exception {
String layerName = randomString();
installLayers(layerName);
TestUtils.tree(env.getInstalledImage().getJbossHome());
InstalledIdentity installedIdentity = loadInstalledIdentity();
Identity identity = installedIdentity.getIdentity();
assertEquals(productConfig.getProductName(), identity.getName());
assertEquals(productConfig.resolveVersion(), identity.getVersion());
List<Layer> layers = installedIdentity.getLayers();
assertEquals(2, layers.size());
Layer layer = layers.get(0);
assertEquals(layerName, layer.getName());
assertEquals(BASE, layers.get(1).getName()); // base layer is always appended
PatchableTarget.TargetInfo targetInfo = layer.loadTargetInfo();
assertEquals(BASE, targetInfo.getCumulativePatchID());
assertTrue(targetInfo.getPatchIDs().isEmpty());
DirectoryStructure directoryStructure = targetInfo.getDirectoryStructure();
assertEquals(newFile(env.getModuleRoot(), "system", "layers", layerName), directoryStructure.getModuleRoot());
assertNull(directoryStructure.getBundleRepositoryRoot());
}
@Test
public void patchLayer() throws Exception {
// add a layer
String layerName = "mylayer";//randomString();
installLayers(layerName);
InstalledIdentity installedIdentity = loadInstalledIdentity();
// build a one-off patch for the layer with 1 added module
// and 1 add file
String patchID = randomString();
File patchDir = mkdir(tempDir, patchID);
String layerPatchId = "mylayerPatchID";//randomString();
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(patchDir, layerPatchId, moduleName);
ContentModification fileAdded = ContentModificationUtils.addMisc(patchDir, patchID, "new file resource", "bin", "my-new-standalone.sh");
Patch patch = PatchBuilder.create()
.setPatchId(patchID)
.oneOffPatchIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion())
.getParent()
.oneOffPatchElement(layerPatchId, layerName, false)
.addContentModification(moduleAdded)
.getParent()
.addContentModification(fileAdded)
.build();
createPatchXMLFile(patchDir, patch);
File zippedPatch = createZippedPatchFile(patchDir, patchID);
// apply patch
PatchingResult result = executePatch(zippedPatch);
assertPatchHasBeenApplied(result, patch);
InstalledIdentity patchedInstalledIdentity = loadInstalledIdentity();
assertInstallationIsPatched(patch, patchedInstalledIdentity.getIdentity().loadTargetInfo());
assertFileExists(env.getInstalledImage().getJbossHome(), "bin", fileAdded.getItem().getName());
DirectoryStructure layerDirStructure = installedIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure();
File modulesPatchDir = layerDirStructure.getModulePatchDirectory(layerPatchId);
assertDirExists(modulesPatchDir);
assertDefinedModule(modulesPatchDir, moduleName, moduleAdded.getItem().getContentHash());
}
@Test
public void patchAndRollbackLayer() throws Exception {
// add a layer
String layerName = randomString();
installLayers(layerName);
InstalledIdentity installedIdentity = loadInstalledIdentity();
PatchableTarget.TargetInfo identityInfo = installedIdentity.getIdentity().loadTargetInfo();
assertEquals(BASE, identityInfo.getCumulativePatchID());
assertTrue(identityInfo.getPatchIDs().isEmpty());
// build a one-off patch for the layer with 1 added module
// and 1 added file
String patchID = randomString();
File patchDir = mkdir(tempDir, patchID);
String layerPatchId = "mylayerPatchID";//randomString();
String moduleName = randomString();
ContentModification moduleAdded = ContentModificationUtils.addModule(patchDir, layerPatchId, moduleName);
ContentModification fileAdded = ContentModificationUtils.addMisc(patchDir, patchID, "new file resource", "bin", "my-new-standalone.sh");
Patch patch = PatchBuilder.create()
.setPatchId(patchID)
.oneOffPatchIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion())
.getParent()
.oneOffPatchElement(layerPatchId, layerName, false)
.addContentModification(moduleAdded)
.getParent()
.addContentModification(fileAdded)
.build();
createPatchXMLFile(patchDir, patch);
File zippedPatch = createZippedPatchFile(patchDir, patchID);
Identity identityBeforePatch = loadInstalledIdentity().getIdentity();
// apply patch
PatchingResult patchResult = executePatch(zippedPatch);
assertPatchHasBeenApplied(patchResult, patch);
// reload the installed identity
InstalledIdentity patchedInstalledIdentity = InstalledIdentity.load(env.getInstalledImage().getJbossHome(), productConfig, env.getInstalledImage().getModulesDir());
assertInstallationIsPatched(patch, patchedInstalledIdentity.getIdentity().loadTargetInfo());
assertFileExists(env.getInstalledImage().getJbossHome(), "bin", fileAdded.getItem().getName());
DirectoryStructure layerDirStructure = patchedInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure();
File modulesPatchDir = layerDirStructure.getModulePatchDirectory(layerPatchId);
assertDirExists(modulesPatchDir);
assertDefinedModule(modulesPatchDir, moduleName, moduleAdded.getItem().getContentHash());
// rollback the patch
PatchingResult rollbackResult = rollback(patchID);
assertPatchHasBeenRolledBack(rollbackResult, identityBeforePatch);
// reload the rolled back installed identity
InstalledIdentity rolledBackInstalledIdentity = InstalledIdentity.load(env.getInstalledImage().getJbossHome(), productConfig, env.getInstalledImage().getModulesDir());
PatchingAssert.assertFileDoesNotExist(env.getInstalledImage().getJbossHome(), "bin", fileAdded.getItem().getName());
if (File.separatorChar != '\\') {
assertDirDoesNotExist(rolledBackInstalledIdentity.getLayers().get(0).loadTargetInfo().getDirectoryStructure().getModulePatchDirectory(layerPatchId));
}
}
@Test
public void duplicateElementId() throws Exception {
// add a layer
String layerName = "layer1";
String layer2Name = "layer2";
installLayers(layerName, layer2Name);
InstalledIdentity installedIdentity = loadInstalledIdentity();
PatchableTarget.TargetInfo identityInfo = installedIdentity.getIdentity().loadTargetInfo();
assertEquals(BASE, identityInfo.getCumulativePatchID());
assertTrue(identityInfo.getPatchIDs().isEmpty());
// build a one-off patch for the layer with 1 added module
// and 1 added file
String patchID = randomString();
File patchDir = mkdir(tempDir, patchID);
String layerPatchId = "mylayerPatchID";
String moduleName = "module1";
ContentModification moduleAdded = ContentModificationUtils.addModule(patchDir, layerPatchId, moduleName);
final PatchBuilder patchBuilder = PatchBuilder.create()
.setPatchId(patchID)
.oneOffPatchIdentity(installedIdentity.getIdentity().getName(), installedIdentity.getIdentity().getVersion())
.getParent()
.oneOffPatchElement(layerPatchId, layerName, false)
.addContentModification(moduleAdded)
.getParent();
try {
patchBuilder.oneOffPatchElement(layerPatchId, layer2Name, false);
fail("duplicate element patch-id error expected");
} catch(IllegalStateException e) {
// expected
}
}
}