use of io.fabric8.gateway.handlers.detecting.protocol.openwire.command.Message in project fabric8 by jboss-fuse.
the class GitPatchManagementServiceImpl method install.
@Override
public void install(String transaction, Patch patch, List<BundleUpdate> bundleUpdatesInThisPatch) {
transactionIsValid(transaction, patch);
Git fork = pendingTransactions.get(transaction);
try {
switch(pendingTransactionsTypes.get(transaction)) {
case ROLLUP:
{
Activator.log2(LogService.LOG_INFO, String.format("Installing rollup patch \"%s\"", patch.getPatchData().getId()));
// we can install only one rollup patch within single transaction
// and it is equal to cherry-picking all user changes on top of transaction branch
// after cherry-picking the commit from the rollup patch branch
// rollup patches do their own update to startup.properties
// we're operating on patch branch, HEAD of the patch branch points to the baseline
ObjectId since = fork.getRepository().resolve("HEAD^{commit}");
// we'll pick all user changes between baseline and main patch branch without P installations
ObjectId to = fork.getRepository().resolve(gitPatchRepository.getMainBranchName() + "^{commit}");
Iterable<RevCommit> mainChanges = fork.log().addRange(since, to).call();
List<RevCommit> userChanges = new LinkedList<>();
// gather lines of HF patches - patches that have *only* bundle updates
// if any of HF patches provide newer version of artifact than currently installed R patch,
// we will leave the relevant line in etc/overrides.properties
List<String> hfChanges = new LinkedList<>();
for (RevCommit rc : mainChanges) {
if (isUserChangeCommit(rc)) {
userChanges.add(rc);
} else {
String hfPatchId = isHfChangeCommit(rc);
if (hfPatchId != null) {
hfChanges.addAll(gatherOverrides(hfPatchId, patch));
}
}
}
String patchRef = patch.getManagedPatch().getCommitId();
if (env == EnvType.STANDALONE_CHILD) {
// we're in a slightly different situation:
// - patch was patch:added in root container
// - its main commit should be used when patching full Fuse/AMQ container
// - it created "side" commits (with tags) for this case of patching admin:create based containers
// - those tags are stored in special patch-info.txt file within patch' commit
String patchInfo = gitPatchRepository.getFileContent(fork, patchRef, "patch-info.txt");
if (patchInfo != null) {
BufferedReader reader = new BufferedReader(new StringReader(patchInfo));
String line = null;
while ((line = reader.readLine()) != null) {
if (line.startsWith("#")) {
continue;
}
Pattern p = Pattern.compile(env.getBaselineTagFormat().replace("%s", "(.*)"));
if (p.matcher(line).matches()) {
// this means we have another commit/tag that we should chery-pick as a patch
// for this standalone child container
patchRef = line.trim();
}
}
} else {
// hmm, we actually can't patch standalone child container then...
Activator.log2(LogService.LOG_WARNING, String.format("Can't install rollup patch \"%s\" in admin container - no information about admin container patch", patch.getPatchData().getId()));
return;
}
}
if (env == EnvType.STANDALONE) {
// pick the rollup patch
fork.cherryPick().include(fork.getRepository().resolve(patchRef)).setNoCommit(true).call();
gitPatchRepository.prepareCommit(fork, String.format(MARKER_R_PATCH_INSTALLATION_PATTERN, patch.getPatchData().getId())).call();
} else if (env == EnvType.STANDALONE_CHILD) {
// rebase on top of rollup patch
fork.reset().setMode(ResetCommand.ResetType.HARD).setRef("refs/tags/" + patchRef + "^{commit}").call();
}
// next commit - reset overrides.properties - this is 2nd step of installing rollup patch
// we are doing it even if the commit is going to be empty - this is the same step as after
// creating initial baseline
resetOverrides(fork.getRepository().getWorkTree(), hfChanges);
fork.add().addFilepattern("etc/overrides.properties").call();
RevCommit c = gitPatchRepository.prepareCommit(fork, String.format(MARKER_R_PATCH_RESET_OVERRIDES_PATTERN, patch.getPatchData().getId())).call();
if (env == EnvType.STANDALONE) {
// tag the new rollup patch as new baseline
String newFuseVersion = determineVersion(fork.getRepository().getWorkTree(), "fuse");
fork.tag().setName(String.format(EnvType.STANDALONE.getBaselineTagFormat(), newFuseVersion)).setObjectId(c).call();
}
// reapply those user changes that are not conflicting
// for each conflicting cherry-pick we do a backup of user files, to be able to restore them
// when rollup patch is rolled back
ListIterator<RevCommit> it = userChanges.listIterator(userChanges.size());
int prefixSize = Integer.toString(userChanges.size()).length();
int count = 1;
while (it.hasPrevious()) {
RevCommit userChange = it.previous();
String prefix = String.format("%0" + prefixSize + "d-%s", count++, userChange.getName());
CherryPickResult result = fork.cherryPick().include(userChange).setNoCommit(true).call();
// ENTESB-5492: remove etc/overrides.properties if there is such file left from old patch
// mechanism
File overrides = new File(fork.getRepository().getWorkTree(), "etc/overrides.properties");
if (overrides.isFile()) {
// version of some bundles, overrides.properties should be kept
if (!(hfChanges.size() > 0 && overrides.length() > 0)) {
overrides.delete();
fork.rm().addFilepattern("etc/overrides.properties").call();
}
}
// if there's conflict here, prefer patch version (which is "ours" (first) in this case)
handleCherryPickConflict(patch.getPatchData().getPatchDirectory(), fork, result, userChange, false, PatchKind.ROLLUP, prefix, true, false);
// always commit even empty changes - to be able to restore user changes when rolling back
// rollup patch.
// commit has the original commit id appended to the message.
// when we rebase on OLDER baseline (rollback) we restore backed up files based on this
// commit id (from patches/patch-id.backup/number-commit directory)
String newMessage = userChange.getFullMessage() + "\n\n";
newMessage += prefix;
gitPatchRepository.prepareCommit(fork, newMessage).call();
// we may have unadded changes - when file mode is changed
fork.reset().setMode(ResetCommand.ResetType.HARD).call();
}
// finally - let's get rid of all the tags related to non-rollup patches installed between
// previous baseline and previous HEAD, because installing rollup patch makes all previous P
// patches obsolete
RevWalk walk = new RevWalk(fork.getRepository());
RevCommit c1 = walk.parseCommit(since);
RevCommit c2 = walk.parseCommit(to);
Map<String, RevTag> tags = gitPatchRepository.findTagsBetween(fork, c1, c2);
for (Map.Entry<String, RevTag> entry : tags.entrySet()) {
if (entry.getKey().startsWith("patch-")) {
fork.tagDelete().setTags(entry.getKey()).call();
fork.push().setRefSpecs(new RefSpec().setSource(null).setDestination("refs/tags/" + entry.getKey())).call();
}
}
break;
}
case NON_ROLLUP:
{
Activator.log2(LogService.LOG_INFO, String.format("Installing non-rollup patch \"%s\"", patch.getPatchData().getId()));
// simply cherry-pick patch commit to transaction branch
// non-rollup patches require manual change to artifact references in all files
// pick the non-rollup patch
RevCommit commit = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve(patch.getManagedPatch().getCommitId()));
CherryPickResult result = fork.cherryPick().include(commit).setNoCommit(true).call();
handleCherryPickConflict(patch.getPatchData().getPatchDirectory(), fork, result, commit, true, PatchKind.NON_ROLLUP, null, true, false);
// there are several files in ${karaf.home} that need to be changed together with patch
// commit, to make them reference updated bundles (paths, locations, ...)
updateFileReferences(fork, patch.getPatchData(), bundleUpdatesInThisPatch);
updateOverrides(fork.getRepository().getWorkTree(), patch.getPatchData());
fork.add().addFilepattern(".").call();
// always commit non-rollup patch
RevCommit c = gitPatchRepository.prepareCommit(fork, String.format(MARKER_P_PATCH_INSTALLATION_PATTERN, patch.getPatchData().getId())).call();
// we may have unadded changes - when file mode is changed
fork.reset().setMode(ResetCommand.ResetType.HARD).call();
// tag the installed patch (to easily rollback and to prevent another installation)
String tagName = String.format("patch-%s", patch.getPatchData().getId().replace(' ', '-'));
if (env == EnvType.STANDALONE_CHILD) {
tagName += "-" + gitPatchRepository.getStandaloneChildkarafName();
}
fork.tag().setName(tagName).setObjectId(c).call();
break;
}
}
} catch (IOException | GitAPIException e) {
throw new PatchException(e.getMessage(), e);
}
}
use of io.fabric8.gateway.handlers.detecting.protocol.openwire.command.Message in project fabric8 by jboss-fuse.
the class GitPatchManagementServiceImpl method findLatestPatchRevision.
@Override
public String findLatestPatchRevision(File gitRepository, String versionId) {
Git git = null;
try {
git = Git.open(gitRepository);
Iterable<RevCommit> log = git.log().add(git.getRepository().resolve(versionId)).call();
List<RevCommit> oldestToNewest = new LinkedList<>();
RevCommit patchBaseRevision = null;
for (RevCommit rc : log) {
// in case we don't find previous R patch, we'll have to find it the hard way
oldestToNewest.add(0, rc);
if (rc.getShortMessage().startsWith("Installing rollup patch ")) {
if (rc.getParents() != null && rc.getParents().length == 2) {
// it's 2nd parent with "Installing profiles from patch ..." message
if (rc.getParents()[0].getShortMessage().startsWith("Installing profiles from patch ")) {
patchBaseRevision = rc.getParents()[0];
break;
} else if (rc.getParents()[1].getShortMessage().startsWith("Installing profiles from patch ")) {
patchBaseRevision = rc.getParents()[1];
break;
}
}
// if "Installing rollup patch ..." commit doesn't have 2 parents, it means it was created by
// some old patch mechanism from early 6.2.1 which just copied profiles over and didn't use
// merging
patchBaseRevision = rc;
break;
}
}
if (patchBaseRevision == null) {
// from this change
for (RevCommit rc : oldestToNewest) {
if (rc.getShortMessage().startsWith("Update configurations for profile: ")) {
patchBaseRevision = rc;
break;
}
}
}
if (patchBaseRevision == null) {
// we didn't find good place to start... we'll start from HEAD then
return versionId;
}
String patchBranchName = String.format("__%s-%d", versionId, new Date().getTime());
Ref branch = git.checkout().setCreateBranch(true).setName(patchBranchName).setStartPoint(patchBaseRevision).call();
return patchBranchName;
} catch (Exception e) {
throw new PatchException(e.getMessage(), e);
} finally {
if (git != null) {
gitPatchRepository.closeRepository(git, false);
}
}
}
use of io.fabric8.gateway.handlers.detecting.protocol.openwire.command.Message in project fabric8 by jboss-fuse.
the class GitPatchManagementServiceImpl method rollback.
@Override
public void rollback(PatchData patchData) {
Git fork = null;
try {
fork = gitPatchRepository.cloneRepository(gitPatchRepository.findOrCreateMainGitRepository(), true);
Ref installationBranch = null;
PatchKind kind = patchData.isRollupPatch() ? PatchKind.ROLLUP : PatchKind.NON_ROLLUP;
switch(kind) {
case ROLLUP:
{
Activator.log2(LogService.LOG_INFO, String.format("Rolling back rollup patch \"%s\"", patchData.getId()));
// rolling back a rollup patch should rebase all user commits on top of current baseline
// to previous baseline
RevTag currentBaseline = gitPatchRepository.findCurrentBaseline(fork);
RevCommit c1 = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve(currentBaseline.getTagName() + "^{commit}"));
// remember the commit to discover P patch tags installed on top of rolledback baseline
RevCommit since = c1;
RevCommit c2 = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve("HEAD"));
RevCommit to = c2;
Iterable<RevCommit> mainChangesSinceRollupPatch = fork.log().addRange(c1, c2).call();
List<RevCommit> userChanges = new LinkedList<>();
for (RevCommit rc : mainChangesSinceRollupPatch) {
if (isUserChangeCommit(rc)) {
userChanges.add(rc);
}
}
if (env == EnvType.STANDALONE) {
// remove the tag
fork.tagDelete().setTags(currentBaseline.getTagName()).call();
}
// baselines are stacked on each other
RevTag previousBaseline = gitPatchRepository.findNthPreviousBaseline(fork, env == EnvType.STANDALONE ? 0 : 1);
c1 = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve(previousBaseline.getTagName() + "^{commit}"));
// hard reset of main patch branch - to point to other branch, originating from previous baseline
fork.reset().setMode(ResetCommand.ResetType.HARD).setRef(previousBaseline.getTagName() + "^{commit}").call();
// reapply those user changes that are not conflicting
ListIterator<RevCommit> it = userChanges.listIterator(userChanges.size());
Status status = fork.status().call();
if (!status.isClean()) {
// unstage any garbage
fork.reset().setMode(ResetCommand.ResetType.MIXED).call();
for (String p : status.getModified()) {
gitPatchRepository.checkout(fork).addPath(p).call();
}
}
while (it.hasPrevious()) {
RevCommit userChange = it.previous();
CherryPickResult cpr = fork.cherryPick().include(userChange.getId()).setNoCommit(true).call();
// this time prefer user change on top of previous baseline - this change shouldn't be
// conflicting, because when rolling back, patch change was preferred over user change
handleCherryPickConflict(patchData.getPatchDirectory(), fork, cpr, userChange, true, PatchKind.ROLLUP, null, false, true);
// restore backed up content from the reapplied user change
String[] commitMessage = userChange.getFullMessage().split("\n\n");
if (commitMessage.length > 1) {
// we have original commit (that had conflicts) stored in this commit's full message
String ref = commitMessage[commitMessage.length - 1];
File backupDir = new File(patchesDir, patchData.getId() + ".backup");
if (isStandaloneChild()) {
backupDir = new File(patchesDir, patchData.getId() + "." + System.getProperty("karaf.name") + ".backup");
}
backupDir = new File(backupDir, ref);
if (backupDir.exists() && backupDir.isDirectory()) {
Activator.log2(LogService.LOG_DEBUG, String.format("Restoring content of %s", backupDir.getCanonicalPath()));
copyManagedDirectories(backupDir, karafBase, false, false, false);
}
}
gitPatchRepository.prepareCommit(fork, userChange.getFullMessage()).call();
}
gitPatchRepository.push(fork);
if (env == EnvType.STANDALONE) {
// remove remote tag
fork.push().setRefSpecs(new RefSpec().setSource(null).setDestination("refs/tags/" + currentBaseline.getTagName())).call();
}
// remove tags related to non-rollup patches installed between
// rolled back baseline and previous HEAD, because rolling back to previous rollup patch
// (previous baseline) equal effectively to starting from fresh baseline
RevWalk walk = new RevWalk(fork.getRepository());
Map<String, RevTag> tags = gitPatchRepository.findTagsBetween(fork, since, to);
for (Map.Entry<String, RevTag> entry : tags.entrySet()) {
if (entry.getKey().startsWith("patch-")) {
fork.tagDelete().setTags(entry.getKey()).call();
fork.push().setRefSpecs(new RefSpec().setSource(null).setDestination("refs/tags/" + entry.getKey())).call();
}
}
// HEAD of main patch branch after reset and cherry-picks
c2 = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve("HEAD"));
// applyChanges(fork, c1, c2);
applyChanges(fork, false);
break;
}
case NON_ROLLUP:
{
Activator.log2(LogService.LOG_INFO, String.format("Rolling back non-rollup patch \"%s\"", patchData.getId()));
// rolling back a non-rollup patch is a revert of the patch commit and removal of patch tag
String patchTagName = String.format("patch-%s", env == EnvType.STANDALONE ? patchData.getId() : patchData.getId() + "-" + gitPatchRepository.getStandaloneChildkarafName());
ObjectId oid = fork.getRepository().resolve(patchTagName);
if (oid == null) {
throw new PatchException(String.format("Can't find installed patch (tag %s is missing)", patchTagName));
}
RevCommit commit = new RevWalk(fork.getRepository()).parseCommit(oid);
RevertCommand revertCommand = fork.revert().include(commit);
RevCommit reverted = revertCommand.call();
if (reverted == null) {
List<String> unmerged = revertCommand.getUnmergedPaths();
Activator.log2(LogService.LOG_WARNING, "Problem rolling back patch \"" + patchData.getId() + "\". The following files where updated later:");
for (String path : unmerged) {
Activator.log2(LogService.LOG_WARNING, " - " + path);
}
RevWalk walk = new RevWalk(fork.getRepository());
RevCommit head = walk.parseCommit(fork.getRepository().resolve("HEAD"));
Map<String, RevTag> tags = gitPatchRepository.findTagsBetween(fork, commit, head);
List<RevTag> laterPatches = new LinkedList<>();
if (tags.size() > 0) {
for (Map.Entry<String, RevTag> tag : tags.entrySet()) {
if (tag.getKey().startsWith("patch-")) {
laterPatches.add(tag.getValue());
}
}
Activator.log2(LogService.LOG_INFO, "The following patches were installed after \"" + patchData.getId() + "\":");
for (RevTag t : laterPatches) {
String message = " - " + t.getTagName().substring("patch-".length());
RevObject object = walk.peel(t);
if (object != null) {
RevCommit c = walk.parseCommit(object.getId());
String date = GitPatchRepository.FULL_DATE.format(new Date(c.getCommitTime() * 1000L));
message += " (" + date + ")";
}
Activator.log2(LogService.LOG_INFO, message);
}
}
return;
}
// TODO: should we restore the backup possibly created when instalilng P patch?
// remove the tag
fork.tagDelete().setTags(patchTagName).call();
gitPatchRepository.push(fork);
// remove remote tag
fork.push().setRefSpecs(new RefSpec().setSource(null).setDestination(String.format("refs/tags/%s", patchTagName))).call();
// HEAD of main patch branch after reset and cherry-picks
RevCommit c = new RevWalk(fork.getRepository()).parseCommit(fork.getRepository().resolve("HEAD"));
applyChanges(fork, c.getParent(0), c);
break;
}
}
} catch (IOException | GitAPIException e) {
throw new PatchException(e.getMessage(), e);
} finally {
if (fork != null) {
gitPatchRepository.closeRepository(fork, true);
}
}
}
use of io.fabric8.gateway.handlers.detecting.protocol.openwire.command.Message in project fabric8 by jboss-fuse.
the class MQManager method createOrUpdateProfile.
/**
* Creates or updates the broker profile for the given DTO and updates the requirements so that the
* minimum number of instances of the profile is updated
*/
public static Profile createOrUpdateProfile(MQBrokerConfigDTO dto, FabricService fabricService, RuntimeProperties runtimeProperties) throws IOException {
FabricRequirements requirements = fabricService.getRequirements();
MQService mqService = createMQService(fabricService, runtimeProperties);
Map<String, String> configuration = new HashMap<String, String>();
List<String> properties = dto.getProperties();
String version = dto.version();
boolean changeInCurrentVersion = requirements.getVersion().equals(dto.getVersion());
if (properties != null) {
for (String entry : properties) {
String[] parts = entry.split("=", 2);
if (parts.length == 2) {
configuration.put(parts[0], parts[1]);
} else {
configuration.put(parts[0], "");
}
}
}
String data = dto.getData();
String profileName = dto.profile();
try {
FabricValidations.validateProfileName(profileName);
} catch (IllegalArgumentException e) {
// we do not want exception in the server log, so print the error message to the console
System.out.println(e.getMessage());
return null;
}
String brokerName = dto.getBrokerName();
if (data == null) {
// lets use a relative path so we work on any karaf container
data = "${runtime.data}" + brokerName;
}
configuration.put(DATA, data);
for (Map.Entry<String, String> port : dto.getPorts().entrySet()) {
configuration.put(port.getKey() + "-port", port.getValue());
}
BrokerKind kind = dto.kind();
configuration.put(KIND, kind.toString());
String config = dto.getConfigUrl();
if (config != null) {
configuration.put(CONFIG_URL, mqService.getConfig(version, config));
}
String group = dto.getGroup();
if (group != null) {
configuration.put(GROUP, group);
}
Maps.setStringValues(configuration, NETWORKS, dto.getNetworks());
String networksUserName = dto.getNetworksUserName();
if (networksUserName != null) {
configuration.put(NETWORK_USER_NAME, networksUserName);
}
String networksPassword = dto.getNetworksPassword();
if (networksPassword != null) {
configuration.put(NETWORK_PASSWORD, networksPassword);
}
String parentProfile = dto.getParentProfile();
if (parentProfile != null) {
configuration.put(PARENT, parentProfile);
}
Boolean ssl = dto.getSsl();
if (ssl != null) {
configuration.put(SSL, ssl.toString());
}
Integer replicas = dto.getReplicas();
if (replicas != null) {
configuration.put(REPLICAS, replicas.toString());
}
Integer minInstances = dto.getMinimumInstances();
if (minInstances != null) {
configuration.put(MINIMUM_INSTANCES, minInstances.toString());
}
Profile profile = mqService.createOrUpdateMQProfile(version, profileName, brokerName, configuration, dto.kind().equals(BrokerKind.Replicated));
String profileId = profile.getId();
ProfileRequirements profileRequirement = requirements.getOrCreateProfileRequirement(profileId);
Integer minimumInstances = profileRequirement.getMinimumInstances();
// lets reload the DTO as we may have inherited some values from the parent profile
List<MQBrokerConfigDTO> list = createConfigDTOs(mqService, profile);
// lets assume 2 required instances for master/slave unless folks use
// N+1 or replicated
int requiredInstances = 2;
if (list.size() == 1) {
MQBrokerConfigDTO loadedDTO = list.get(0);
requiredInstances = loadedDTO.requiredInstances();
} else {
// assume N+1 broker as there's more than one broker in the profile; so lets set the required size to N+1
requiredInstances = list.size() + 1;
}
if (changeInCurrentVersion && (minimumInstances == null || minimumInstances.intValue() < requiredInstances)) {
profileRequirement.setMinimumInstances(requiredInstances);
fabricService.setRequirements(requirements);
}
String clientProfile = dto.clientProfile();
if (Strings.isNotBlank(clientProfile)) {
String clientParentProfile = dto.getClientParentProfile();
if (Strings.isNullOrBlank(clientParentProfile)) {
clientParentProfile = "mq-client-base";
}
mqService.createOrUpdateMQClientProfile(version, clientProfile, group, clientParentProfile);
}
return profile;
}
use of io.fabric8.gateway.handlers.detecting.protocol.openwire.command.Message in project fabric8 by jboss-fuse.
the class FabricManagerTest method fromJson.
@Test
public void fromJson() throws IOException {
JMXResult res = om().readValue("{\"correlationId\":\"id\",\"code\":0,\"message\":\"OK\",\"response\":{\"@class\":\"io.fabric8.api.commands.GitVersions\",\"versions\":[{\"version\":\"1.0\",\"sha1\":\"SHA1\",\"timestamp\":null,\"message\":null},{\"version\":\"1.0\",\"sha1\":\"SHA1\",\"timestamp\":null,\"message\":null},{\"version\":\"1.0\",\"sha1\":\"SHA1\",\"timestamp\":null,\"message\":null}]}}", JMXResult.class);
assertNotNull(res);
assertThat(res.getMessage(), equalTo("OK"));
assertThat(((GitVersions) res.getResponse()).getVersions().get(2).getSha1(), equalTo("SHA1"));
assertThat(((GitVersions) res.getResponse()).getVersions().size(), equalTo(3));
}
Aggregations