use of org.jboss.as.patching.metadata.Patch in project wildfly-core by wildfly.
the class LayerTestCase method patchLayer.
@Test
public void patchLayer() throws Exception {
// add a layer
// randomString();
String layerName = "mylayer";
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);
// randomString();
String layerPatchId = "mylayerPatchID";
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());
}
use of org.jboss.as.patching.metadata.Patch in project wildfly-core by wildfly.
the class IdentityPatchRunner method applyPatch.
/**
* Apply a patch.
*
* @param patchId the patch id
* @param patch the patch metadata
* @param context the patch context
* @throws PatchingException
* @throws IOException
* @throws XMLStreamException
*/
private PatchingResult applyPatch(final String patchId, final Patch patch, final IdentityPatchContext context) throws PatchingException, IOException, XMLStreamException {
final Identity identity = patch.getIdentity();
final Patch.PatchType patchType = identity.getPatchType();
final InstallationManager.InstallationModification modification = context.getModification();
if (patchType == Patch.PatchType.CUMULATIVE) {
// Invalidate all installed patches (one-off, cumulative) - we never need to invalidate the release base
final List<String> invalidation = new ArrayList<String>(modification.getPatchIDs());
if (!invalidation.isEmpty()) {
try {
// Before rolling back the one-off patches, validate that the state until that point is consistent
validateRollbackState(invalidation.get(invalidation.size() - 1), modification.getUnmodifiedInstallationState());
} catch (PatchingException e) {
throw e;
} catch (Exception e) {
throw new PatchingException(e);
}
// Invalidate the installed patches first
for (final String rollback : invalidation) {
rollback(rollback, context);
}
}
}
// Add to installed patches list
modification.addInstalledPatch(patchId);
// Then apply the current patch
for (final PatchElement element : patch.getElements()) {
// Apply the content modifications
final IdentityPatchContext.PatchEntry target = context.resolveForElement(element);
final PatchElementProvider provider = element.getProvider();
final Patch.PatchType elementPatchType = provider.getPatchType();
final String elementPatchId = element.getId();
// See if we can skip this element
if (target.isApplied(elementPatchId)) {
// This needs some further testing, maybe we need to compare our history with the patch if they are consistent
throw PatchLogger.ROOT_LOGGER.alreadyApplied(elementPatchId);
}
// Check upgrade conditions
checkUpgradeConditions(provider, target);
apply(elementPatchId, element.getModifications(), target);
target.apply(elementPatchId, elementPatchType);
}
// Apply the patch to the identity
final IdentityPatchContext.PatchEntry identityEntry = context.getIdentityEntry();
apply(patchId, patch.getModifications(), identityEntry);
identityEntry.apply(patchId, patchType);
// Port forward missing module changes
if (patchType == Patch.PatchType.CUMULATIVE) {
portForward(patch, context);
}
// We need the resulting version for rollback
if (patchType == Patch.PatchType.CUMULATIVE) {
final Identity.IdentityUpgrade upgrade = identity.forType(Patch.PatchType.CUMULATIVE, Identity.IdentityUpgrade.class);
identityEntry.setResultingVersion(upgrade.getResultingVersion());
}
// Execute the tasks
final IdentityApplyCallback callback = new IdentityApplyCallback(patch, identityEntry.getDirectoryStructure());
try {
return executeTasks(context, callback);
} catch (Exception e) {
context.cancel(callback);
throw rethrowException(e);
}
}
use of org.jboss.as.patching.metadata.Patch in project wildfly-core by wildfly.
the class IdentityPatchRunner method reenableNotOverridenModules.
void reenableNotOverridenModules(final RollbackPatch patch, IdentityPatchContext context) throws PatchingException, IOException, XMLStreamException {
assert patch.getIdentity().getPatchType() == Patch.PatchType.CUMULATIVE;
final Iterator historyIterator = context.getHistory().iterator(patch.getIdentityState().getIdentity().loadTargetInfo());
if (!historyIterator.hasNext()) {
return;
}
final List<PatchElement> elements = patch.getElements();
final Map<String, List<PatchElement>> layerPatches = new HashMap<String, List<PatchElement>>(elements.size());
final Map<String, List<PatchElement>> addonPatches = new HashMap<String, List<PatchElement>>(elements.size());
for (PatchElement e : elements) {
if (e.getProvider().isAddOn()) {
addonPatches.put(e.getProvider().getName(), Collections.<PatchElement>emptyList());
} else {
layerPatches.put(e.getProvider().getName(), Collections.<PatchElement>emptyList());
}
}
Patch prevCP = null;
while (historyIterator.hasNext()) {
final Entry entry = historyIterator.next();
if (entry.getType() == PatchType.CUMULATIVE) {
prevCP = entry.getMetadata();
break;
}
final Patch oneOff = entry.getMetadata();
for (PatchElement oneOffElement : oneOff.getElements()) {
final Map<String, List<PatchElement>> providerPatches;
if (oneOffElement.getProvider().isAddOn()) {
providerPatches = addonPatches;
} else {
providerPatches = layerPatches;
}
List<PatchElement> patches = providerPatches.get(oneOffElement.getProvider().getName());
if (patches != null) {
switch(patches.size()) {
case 0:
providerPatches.put(oneOffElement.getProvider().getName(), Collections.singletonList(oneOffElement));
break;
case 1:
patches = new ArrayList<PatchElement>(patches);
providerPatches.put(oneOffElement.getProvider().getName(), patches);
default:
patches.add(oneOffElement);
}
}
}
}
Set<ModuleItem> cpElementModules;
Set<ModuleItem> reenabledModules = Collections.emptySet();
for (PatchElement e : elements) {
final List<PatchElement> patches;
if (e.getProvider().isAddOn()) {
patches = addonPatches.get(e.getProvider().getName());
} else {
patches = layerPatches.get(e.getProvider().getName());
}
if (patches.isEmpty()) {
continue;
}
cpElementModules = null;
final PatchEntry rollbackEntry = context.resolveForElement(e);
for (PatchElement oneOff : patches) {
for (ContentModification mod : oneOff.getModifications()) {
if (mod.getItem().getContentType() != ContentType.MODULE) {
continue;
}
final ModuleItem module = (ModuleItem) mod.getItem();
if (rollbackEntry.get(new Location(module)) != null) {
continue;
}
if (reenabledModules.contains(module)) {
continue;
}
final File modulePath = PatchContentLoader.getModulePath(rollbackEntry.getDirectoryStructure().getModulePatchDirectory(oneOff.getId()), module);
rollbackEntry.invalidateRoot(modulePath);
if (reenabledModules.isEmpty()) {
reenabledModules = new HashSet<ModuleItem>();
}
reenabledModules.add(module);
if (prevCP == null) {
rollbackEntry.disableBaseModule(module);
} else {
if (cpElementModules == null) {
for (PatchElement cpE : prevCP.getElements()) {
if (cpE.getProvider().getName().equals(e.getProvider().getName()) && cpE.getProvider().getLayerType().equals(e.getProvider().getLayerType())) {
cpElementModules = new HashSet<ModuleItem>(cpE.getModifications().size());
for (ContentModification cpMod : cpE.getModifications()) {
if (cpMod.getItem().getContentType() == ContentType.MODULE) {
cpElementModules.add(cpMod.getItem(ModuleItem.class));
}
}
break;
}
}
}
if (cpElementModules != null && !cpElementModules.contains(module)) {
rollbackEntry.disableBaseModule(module);
}
}
}
}
}
}
use of org.jboss.as.patching.metadata.Patch in project wildfly-core by wildfly.
the class IdentityPatchRunner method portForward.
/**
* Port forward missing module changes for each layer.
*
* @param patch the current patch
* @param context the patch context
* @throws PatchingException
* @throws IOException
* @throws XMLStreamException
*/
void portForward(final Patch patch, IdentityPatchContext context) throws PatchingException, IOException, XMLStreamException {
assert patch.getIdentity().getPatchType() == Patch.PatchType.CUMULATIVE;
final PatchingHistory history = context.getHistory();
for (final PatchElement element : patch.getElements()) {
final PatchElementProvider provider = element.getProvider();
final String name = provider.getName();
final boolean addOn = provider.isAddOn();
final IdentityPatchContext.PatchEntry target = context.resolveForElement(element);
final String cumulativePatchID = target.getCumulativePatchID();
if (Constants.BASE.equals(cumulativePatchID)) {
reenableRolledBackInBase(target);
continue;
}
boolean found = false;
final PatchingHistory.Iterator iterator = history.iterator();
while (iterator.hasNextCP()) {
final PatchingHistory.Entry entry = iterator.nextCP();
final String patchId = addOn ? entry.getAddOnPatches().get(name) : entry.getLayerPatches().get(name);
if (patchId != null && patchId.equals(cumulativePatchID)) {
final Patch original = loadPatchInformation(entry.getPatchId(), installedImage);
for (final PatchElement originalElement : original.getElements()) {
if (name.equals(originalElement.getProvider().getName()) && addOn == originalElement.getProvider().isAddOn()) {
PatchingTasks.addMissingModifications(target, originalElement.getModifications(), ContentItemFilter.ALL_BUT_MISC);
}
}
// Record a loader to have access to the current modules
final DirectoryStructure structure = target.getDirectoryStructure();
final File modulesRoot = structure.getModulePatchDirectory(patchId);
final File bundlesRoot = structure.getBundlesPatchDirectory(patchId);
final PatchContentLoader loader = PatchContentLoader.create(null, bundlesRoot, modulesRoot);
context.recordContentLoader(patchId, loader);
found = true;
break;
}
}
if (!found) {
throw PatchLogger.ROOT_LOGGER.patchNotFoundInHistory(cumulativePatchID);
}
reenableRolledBackInBase(target);
}
}
use of org.jboss.as.patching.metadata.Patch in project wildfly-core by wildfly.
the class IdentityPatchContext method finalize.
/**
* Finalize the patch.
*
* @param callback the finalize callback
* @return the result
* @throws Exception
*/
protected PatchingResult finalize(final FinalizeCallback callback) throws Exception {
assert state == State.NEW;
final Patch original = callback.getPatch();
final Patch.PatchType patchType = original.getIdentity().getPatchType();
final String patchId;
if (patchType == Patch.PatchType.CUMULATIVE) {
patchId = modification.getCumulativePatchID();
} else {
patchId = original.getPatchId();
}
try {
// The processed patch, based on the recorded changes
final Patch processedPatch = createProcessedPatch(original);
// The rollback containing all the recorded rollback actions
final RollbackPatch rollbackPatch = createRollbackPatch(patchId, patchType);
callback.finishPatch(processedPatch, rollbackPatch, this);
} catch (Exception e) {
if (undoChanges()) {
callback.operationCancelled(this);
}
throw e;
}
state = State.PREPARED;
return new PatchingResult() {
@Override
public String getPatchId() {
return original.getPatchId();
}
@Override
public PatchInfo getPatchInfo() {
return new PatchInfo() {
@Override
public String getVersion() {
return identityEntry.getResultingVersion();
}
@Override
public String getCumulativePatchID() {
return identityEntry.delegate.getModifiedState().getCumulativePatchID();
}
@Override
public List<String> getPatchIDs() {
return identityEntry.delegate.getModifiedState().getPatchIDs();
}
};
}
@Override
public void commit() {
if (state == State.PREPARED) {
complete(modification, callback);
} else {
undoChanges();
throw new IllegalStateException();
}
}
@Override
public void rollback() {
if (undoChanges()) {
try {
callback.operationCancelled(IdentityPatchContext.this);
} finally {
modification.cancel();
}
}
}
};
}
Aggregations