use of io.fabric8.patch.management.Utils.mvnurlToArtifact in project fabric8 by jboss-fuse.
the class GitPatchManagementServiceImpl method gatherOverrides.
/**
* Returns list of bundle updates (maven coordinates) from HF/P patch that should be preserved during
* installation of R patch
* @param hfPatchId ID of patch that was detected to be HF patch
* @param patch currently installed R patch
* @return
*/
private List<String> gatherOverrides(String hfPatchId, Patch patch) {
Patch hf = loadPatch(new PatchDetailsRequest(hfPatchId));
List<String> result = new LinkedList<>();
if (hf != null && hf.getPatchData() != null) {
result.addAll(hf.getPatchData().getBundles());
// leave only these artifacts that are in newer version than in R patch being installed
if (patch != null && patch.getPatchData() != null) {
Map<String, Artifact> cache = new HashMap<>();
for (String bu : patch.getPatchData().getBundles()) {
Artifact rPatchArtifact = Utils.mvnurlToArtifact(bu, true);
if (rPatchArtifact != null) {
cache.put(String.format("%s:%s", rPatchArtifact.getGroupId(), rPatchArtifact.getArtifactId()), rPatchArtifact);
}
}
for (String bu : hf.getPatchData().getBundles()) {
Artifact hfPatchArtifact = Utils.mvnurlToArtifact(bu, true);
String key = String.format("%s:%s", hfPatchArtifact.getGroupId(), hfPatchArtifact.getArtifactId());
if (cache.containsKey(key)) {
Version hfVersion = Utils.getOsgiVersion(hfPatchArtifact.getVersion());
Version rVersion = Utils.getOsgiVersion(cache.get(key).getVersion());
if (rVersion.compareTo(hfVersion) >= 0) {
result.remove(bu);
}
}
}
}
}
return result;
}
use of io.fabric8.patch.management.Utils.mvnurlToArtifact in project fabric8 by jboss-fuse.
the class GitPatchManagementServiceImpl method trackPatch.
/**
* <p>This method turns static information about a patch into managed patch - i.e., patch added to git
* repository.</p>
*
* <p>Such patch has its own branch ready to be merged (when patch is installed). Before installation we can verify
* the patch,
* examine the content, check the differences, conflicts and perform simulation (merge to temporary branch created
* from main patch branch)</p>
*
* <p>The strategy is as follows:<ul>
* <li><em>main patch branch</em> in git repository tracks all changes (from baselines, patch-management
* system, patches and user changes)</li>
* <li>Initially there are 3 commits: baseline, patch-management bundle installation in etc/startup.properties,
* initial user changes</li>
* <li>We always <strong>tag the baseline commit</strong></li>
* <li>User changes may be applied each time Framework is restarted</li>
* <li>When we add a patch, we create <em>named branch</em> from the <strong>latest baseline</strong></li>
* <li>When we install a patch, we <strong>merge</strong> the patch branch with the <em>main patch branch</em>
* (that may contain additional user changes)</li>
* <li>When patch ZIP contains new baseline distribution, after merging patch branch, we tag the merge commit
* in <em>main patch branch</em> branch as new baseline</li>
* <li>Branches for new patches will then be created from new baseline commit</li>
* </ul></p>
* @param patchData
* @return
*/
@Override
public Patch trackPatch(PatchData patchData) throws PatchException {
try {
awaitInitialization();
} catch (InterruptedException e) {
throw new PatchException("Patch management system is not ready yet");
}
Git fork = null;
try {
Git mainRepository = gitPatchRepository.findOrCreateMainGitRepository();
// prepare single fork for all the below operations
fork = gitPatchRepository.cloneRepository(mainRepository, true);
// 1. find current baseline
RevTag latestBaseline = gitPatchRepository.findCurrentBaseline(fork);
if (latestBaseline == null) {
throw new PatchException("Can't find baseline distribution tracked in patch management. Is patch management initialized?");
}
// the commit from the patch should be available from main patch branch
RevCommit commit = new RevWalk(fork.getRepository()).parseCommit(latestBaseline.getObject());
// create dedicated branch for this patch. We'll immediately add patch content there so we can examine the
// changes from the latest baseline
gitPatchRepository.checkout(fork).setCreateBranch(true).setName("patch-" + patchData.getId()).setStartPoint(commit).call();
// copy patch resources (but not maven artifacts from system/ or repository/) to working copy
if (patchData.getPatchDirectory() != null) {
boolean removeTargetDir = patchData.isRollupPatch();
copyManagedDirectories(patchData.getPatchDirectory(), fork.getRepository().getWorkTree(), removeTargetDir, false, false);
}
// add the changes
fork.add().addFilepattern(".").call();
// remove the deletes (without touching specially-managed etc/overrides.properties)
for (String missing : fork.status().call().getMissing()) {
if (!"etc/overrides.properties".equals(missing)) {
fork.rm().addFilepattern(missing).call();
}
}
// record information about other "patches" included in added patch (e.g., Fuse patch
// may contain patches to admin:create based containers in standalone mode)
StringWriter sw = new StringWriter();
sw.append("# tags for patches included in \"").append(patchData.getId()).append("\"\n");
for (String bundle : patchData.getBundles()) {
// containers that want to patch:install patches added in root containers
if (bundle.contains("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/")) {
Artifact a = Utils.mvnurlToArtifact(bundle, true);
if (a != null) {
sw.append(String.format(EnvType.STANDALONE_CHILD.getBaselineTagFormat(), a.getVersion())).append("\n");
}
break;
}
}
FileUtils.write(new File(fork.getRepository().getWorkTree(), "patch-info.txt"), sw.toString());
fork.add().addFilepattern(".").call();
// commit the changes (patch vs. baseline) to patch branch
gitPatchRepository.prepareCommit(fork, String.format("[PATCH] Tracking patch %s", patchData.getId())).call();
// push the patch branch
gitPatchRepository.push(fork, "patch-" + patchData.getId());
// track other kinds of baselines found in the patch
if (env.isFabric()) {
trackBaselinesForRootContainer(fork);
trackBaselinesForChildContainers(fork);
trackBaselinesForSSHContainers(fork);
} else {
// for admin:create child containers
trackBaselinesForChildContainers(fork);
}
return new Patch(patchData, gitPatchRepository.getManagedPatch(patchData.getId()));
} catch (IOException | GitAPIException e) {
throw new PatchException(e.getMessage(), e);
} finally {
if (fork != null) {
gitPatchRepository.closeRepository(fork, true);
}
}
}
use of io.fabric8.patch.management.Utils.mvnurlToArtifact in project fabric8 by jboss-fuse.
the class ServiceImpl method bundleUpdatesInPatch.
/**
* Returns a list of {@link BundleUpdate} for single patch, taking into account already discovered updates
* @param patch
* @param allBundles
* @param bundleUpdateLocations out parameter that gathers update locations for bundles across patches
* @param history
* @param updatesForBundleKeys
* @param kind
* @param coreBundles
* @param featureUpdatesInThisPatch
* @return
* @throws IOException
*/
private List<BundleUpdate> bundleUpdatesInPatch(Patch patch, Bundle[] allBundles, Map<Bundle, String> bundleUpdateLocations, BundleVersionHistory history, Map<String, BundleUpdate> updatesForBundleKeys, PatchKind kind, Map<String, Bundle> coreBundles, List<FeatureUpdate> featureUpdatesInThisPatch) throws Exception {
List<BundleUpdate> updatesInThisPatch = new LinkedList<>();
// for ROLLUP patch we can check which bundles AREN'T updated by this patch - we have to reinstall them
// at the same version as existing one. "no update" means "require install after clearing cache"
// Initially all bundles need update. If we find an update in patch, we remove a key from this map
Map<String, Bundle> updateNotRequired = new LinkedHashMap<>();
// // let's keep {symbolic name -> list of versions} mapping
// MultiMap<String, Version> allBundleVersions = new MultiMap<>();
// bundle location -> bundle key (symbolic name|updateable version)
Map<String, String> locationsOfBundleKeys = new HashMap<>();
for (Bundle b : allBundles) {
if (b.getSymbolicName() == null) {
continue;
}
Version v = b.getVersion();
Version updateableVersion = new Version(v.getMajor(), v.getMinor(), 0);
String key = String.format("%s|%s", stripSymbolicName(b.getSymbolicName()), updateableVersion.toString());
// symbolic name, differing at micro version only
if (!coreBundles.containsKey(stripSymbolicName(b.getSymbolicName()))) {
updateNotRequired.put(key, b);
} else {
// let's key core (etc/startup.properties) bundles by symbolic name only - there should be only
// one version of symbolic name
updateNotRequired.put(stripSymbolicName(b.getSymbolicName()), b);
}
// allBundleVersions.put(stripSymbolicName(b.getSymbolicName()), b.getVersion());
String location = b.getLocation();
if (location != null && location.startsWith("mvn:") && location.contains("//")) {
// special case for mvn:org.ops4j.pax.url/pax-url-wrap/2.4.7//uber
location = location.replace("//", "/jar/");
}
locationsOfBundleKeys.put(location, key);
}
// let's prepare a set of bundle keys that are part of features that will be updated/reinstalled - those
// bundle keys don't have to be reinstalled separately
Set<String> bundleKeysFromFeatures = new HashSet<>();
if (featureUpdatesInThisPatch != null) {
for (FeatureUpdate featureUpdate : featureUpdatesInThisPatch) {
if (featureUpdate.getName() != null) {
// this is either installation or update of single feature
String fName = featureUpdate.getName();
String fVersion = featureUpdate.getPreviousVersion();
Feature f = featuresService.getFeature(fName, fVersion);
for (BundleInfo bundleInfo : f.getBundles()) {
if (/*!bundleInfo.isDependency() && */
locationsOfBundleKeys.containsKey(bundleInfo.getLocation())) {
bundleKeysFromFeatures.add(locationsOfBundleKeys.get(bundleInfo.getLocation()));
}
}
for (Conditional cond : f.getConditional()) {
for (BundleInfo bundleInfo : cond.getBundles()) {
if (/*!bundleInfo.isDependency() && */
locationsOfBundleKeys.containsKey(bundleInfo.getLocation())) {
bundleKeysFromFeatures.add(locationsOfBundleKeys.get(bundleInfo.getLocation()));
}
}
}
}
}
}
for (String newLocation : patch.getPatchData().getBundles()) {
// [symbolicName, version] of the new bundle
String[] symbolicNameVersion = helper.getBundleIdentity(newLocation);
if (symbolicNameVersion == null || symbolicNameVersion[0] == null) {
continue;
}
String sn = stripSymbolicName(symbolicNameVersion[0]);
String vr = symbolicNameVersion[1];
Version newVersion = VersionTable.getVersion(vr);
Version updateableVersion = new Version(newVersion.getMajor(), newVersion.getMinor(), 0);
// this bundle update from a patch may be applied only to relevant bundle|updateable-version, not to
// *every* bundle with exact symbolic name
String key = null;
if (!coreBundles.containsKey(sn)) {
key = String.format("%s|%s", sn, updateableVersion.toString());
} else {
key = sn;
}
// if existing bundle is within this range, update is possible
VersionRange range = getUpdateableRange(patch, newLocation, newVersion);
if (coreBundles.containsKey(sn)) {
// so we lower down the lowest possible version of core bundle that we can update
if (range == null) {
range = new VersionRange(false, Version.emptyVersion, newVersion, true);
} else {
range = new VersionRange(false, Version.emptyVersion, range.getCeiling(), true);
}
} else if (range != null) {
// if range is specified on non core bundle, the key should be different - updateable
// version should be taken from range
key = String.format("%s|%s", sn, range.getFloor().toString());
}
Bundle bundle = updateNotRequired.get(key);
if (bundle == null && coreBundles.containsKey(sn)) {
bundle = updateNotRequired.get(sn);
}
if (bundle == null || range == null) {
// this patch ships a bundle that can't be used as an update for ANY currently installed bundle
if (kind == PatchKind.NON_ROLLUP) {
// which is strange, because non rollup patches should update existing bundles...
if (range == null) {
System.err.printf("Skipping bundle %s - unable to process bundle without a version range configuration%n", newLocation);
} else {
// range is fine, we simply didn't find installed bundle at all - bundle from patch
// will be stored in ${karaf.default.repository}, but not used as an update
}
}
continue;
}
Version oldVersion = bundle.getVersion();
if (range.contains(oldVersion)) {
String oldLocation = history.getLocation(bundle);
if ("org.ops4j.pax.url.mvn".equals(sn)) {
Artifact artifact = Utils.mvnurlToArtifact(newLocation, true);
if (artifact != null) {
URL location = new File(repository, String.format("org/ops4j/pax/url/pax-url-aether/%1$s/pax-url-aether-%1$s.jar", artifact.getVersion())).toURI().toURL();
newLocation = location.toString();
}
}
int startLevel = bundle.adapt(BundleStartLevel.class).getStartLevel();
int state = bundle.getState();
BundleUpdate update = new BundleUpdate(sn, newVersion.toString(), newLocation, oldVersion.toString(), oldLocation, startLevel, state);
if (bundleKeysFromFeatures.contains(key) || coreBundles.containsKey(sn)) {
update.setIndependent(false);
}
updatesInThisPatch.add(update);
updateNotRequired.remove(key);
if (coreBundles.containsKey(sn)) {
updateNotRequired.remove(sn);
}
// Merge result
BundleUpdate oldUpdate = updatesForBundleKeys.get(key);
if (oldUpdate != null) {
Version upv = null;
if (oldUpdate.getNewVersion() != null) {
upv = VersionTable.getVersion(oldUpdate.getNewVersion());
}
if (upv == null || upv.compareTo(newVersion) < 0) {
// other patch contains newer update for a bundle
updatesForBundleKeys.put(key, update);
bundleUpdateLocations.put(bundle, newLocation);
}
} else {
// this is the first update of the bundle
updatesForBundleKeys.put(key, update);
bundleUpdateLocations.put(bundle, newLocation);
}
}
}
if (kind == PatchKind.ROLLUP) {
// user features) and we have (at least try) to install them after restart.
for (Bundle b : updateNotRequired.values()) {
if (b.getSymbolicName() == null) {
continue;
}
String symbolicName = stripSymbolicName(b.getSymbolicName());
Version v = b.getVersion();
Version updateableVersion = new Version(v.getMajor(), v.getMinor(), 0);
String key = String.format("%s|%s", symbolicName, updateableVersion.toString());
int startLevel = b.adapt(BundleStartLevel.class).getStartLevel();
int state = b.getState();
BundleUpdate update = new BundleUpdate(symbolicName, null, null, v.toString(), history.getLocation(b), startLevel, state);
if (bundleKeysFromFeatures.contains(key) || coreBundles.containsKey(symbolicName)) {
// we don't have to install it separately
update.setIndependent(false);
}
updatesInThisPatch.add(update);
updatesForBundleKeys.put(key, update);
}
}
return updatesInThisPatch;
}
use of io.fabric8.patch.management.Utils.mvnurlToArtifact in project fabric8 by jboss-fuse.
the class ServiceImplTest method bundleUpdatesInPatch.
@Test
public void bundleUpdatesInPatch() throws Exception {
BundleContext context = EasyMock.createMock(BundleContext.class);
Bundle bundle0 = createMock(Bundle.class);
expect(bundle0.getBundleContext()).andReturn(context);
replay(bundle0);
expect(context.getProperty("karaf.home")).andReturn("target/bundleUpdatesInPatch").anyTimes();
expect(context.getProperty("karaf.base")).andReturn("target/bundleUpdatesInPatch").anyTimes();
expect(context.getProperty("karaf.data")).andReturn("target/bundleUpdatesInPatch/data").anyTimes();
expect(context.getProperty("karaf.name")).andReturn("root").anyTimes();
expect(context.getProperty("karaf.instances")).andReturn("instances").anyTimes();
expect(context.getProperty("karaf.default.repository")).andReturn("system");
expect(context.getProperty("fuse.patch.location")).andReturn(null);
expect(context.getBundle(0)).andReturn(bundle0);
replay(context);
ServiceImpl service = new ServiceImpl();
Method m = service.getClass().getDeclaredMethod("bundleUpdatesInPatch", Patch.class, Bundle[].class, Map.class, ServiceImpl.BundleVersionHistory.class, Map.class, PatchKind.class, Map.class, List.class);
m.setAccessible(true);
Field f = service.getClass().getDeclaredField("helper");
f.setAccessible(true);
f.set(service, new OSGiPatchHelper(new File("target/bundleUpdatesInPatch"), context) {
@Override
public String[] getBundleIdentity(String url) throws IOException {
Artifact a = Utils.mvnurlToArtifact(url, false);
return new String[] { a.getArtifactId(), a.getVersion() };
}
});
PatchData pd = new PatchData("patch-x");
// for these two, bundle.getLocation() will return matching location
pd.getBundles().add("mvn:io.fabric8/pax-romana/1.0.1");
pd.getBundles().add("mvn:io.fabric8/pax-hellenica/1.0.1/jar");
// for these two, bundle.getLocation() will return non-matching location
pd.getBundles().add("mvn:io.fabric8/pax-bohemia/1.0.1");
pd.getBundles().add("mvn:io.fabric8/pax-pomerania/1.0.1/jar");
// for these two, bundle.getLocation() will return matching location
pd.getBundles().add("mvn:io.fabric8/pax-avaria/1.0.1/jar/uber");
pd.getBundles().add("mvn:io.fabric8/pax-mazovia/1.0.1//uber");
// for these two, bundle.getLocation() will return non-matching location
pd.getBundles().add("mvn:io.fabric8/pax-novgorod/1.0.1/jar/uber");
pd.getBundles().add("mvn:io.fabric8/pax-castile/1.0.1//uber");
f = pd.getClass().getDeclaredField("versionRanges");
f.setAccessible(true);
f.set(pd, new HashMap<>());
Patch patch = new Patch(pd, null);
Bundle[] bundles = new Bundle[8];
bundles[0] = bundle("mvn:io.fabric8/pax-romana/1.0.0");
bundles[1] = bundle("mvn:io.fabric8/pax-hellenica/1.0.0/jar");
bundles[2] = bundle("mvn:io.fabric8/pax-bohemia/1.0.0/jar");
bundles[3] = bundle("mvn:io.fabric8/pax-pomerania/1.0.0");
bundles[4] = bundle("mvn:io.fabric8/pax-avaria/1.0.0/jar/uber");
bundles[5] = bundle("mvn:io.fabric8/pax-mazovia/1.0.0//uber");
bundles[6] = bundle("mvn:io.fabric8/pax-novgorod/1.0.0//uber");
bundles[7] = bundle("mvn:io.fabric8/pax-castile/1.0.0/jar/uber");
Object _list = m.invoke(service, patch, bundles, new HashMap<>(), new ServiceImpl.BundleVersionHistory(new HashMap<String, Patch>()), new HashMap<>(), PatchKind.NON_ROLLUP, new HashMap<>(), null);
List<BundleUpdate> list = (List<BundleUpdate>) _list;
assertThat(list.size(), equalTo(8));
assertThat(list.get(0).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-romana/1.0.0"));
assertThat(list.get(1).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-hellenica/1.0.0/jar"));
assertThat(list.get(2).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-bohemia/1.0.0/jar"));
assertThat(list.get(3).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-pomerania/1.0.0"));
assertThat(list.get(4).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-avaria/1.0.0/jar/uber"));
assertThat(list.get(5).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-mazovia/1.0.0//uber"));
assertThat(list.get(6).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-novgorod/1.0.0//uber"));
assertThat(list.get(7).getPreviousLocation(), equalTo("mvn:io.fabric8/pax-castile/1.0.0/jar/uber"));
assertThat(list.get(0).getNewLocation(), equalTo("mvn:io.fabric8/pax-romana/1.0.1"));
assertThat(list.get(1).getNewLocation(), equalTo("mvn:io.fabric8/pax-hellenica/1.0.1/jar"));
assertThat(list.get(2).getNewLocation(), equalTo("mvn:io.fabric8/pax-bohemia/1.0.1"));
assertThat(list.get(3).getNewLocation(), equalTo("mvn:io.fabric8/pax-pomerania/1.0.1/jar"));
assertThat(list.get(4).getNewLocation(), equalTo("mvn:io.fabric8/pax-avaria/1.0.1/jar/uber"));
assertThat(list.get(5).getNewLocation(), equalTo("mvn:io.fabric8/pax-mazovia/1.0.1//uber"));
assertThat(list.get(6).getNewLocation(), equalTo("mvn:io.fabric8/pax-novgorod/1.0.1/jar/uber"));
assertThat(list.get(7).getNewLocation(), equalTo("mvn:io.fabric8/pax-castile/1.0.1//uber"));
// ---
Repository repository = createMock(Repository.class);
File tmp = new File("target/bundleUpdatesInPatch/" + UUID.randomUUID().toString());
tmp.mkdirs();
File startupProperties = new File(tmp, "etc/startup.properties");
FileUtils.copyFile(new File("src/test/resources/uber-startup.properties"), startupProperties);
expect(repository.getWorkTree()).andReturn(tmp).anyTimes();
replay(repository);
Git fork = createMock(Git.class);
expect(fork.getRepository()).andReturn(repository).anyTimes();
replay(fork);
GitPatchManagementServiceImpl gitPatchManagementService = new GitPatchManagementServiceImpl(context);
m = gitPatchManagementService.getClass().getDeclaredMethod("updateFileReferences", Git.class, PatchData.class, List.class);
m.setAccessible(true);
m.invoke(gitPatchManagementService, fork, pd, list);
try (FileReader reader = new FileReader(startupProperties)) {
Properties startup = new Properties();
startup.load(reader);
assertTrue(startup.containsKey("io/fabric8/pax-romana/1.0.1/pax-romana-1.0.1.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-hellenica/1.0.1/pax-hellenica-1.0.1.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-bohemia/1.0.1/pax-bohemia-1.0.1.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-pomerania/1.0.1/pax-pomerania-1.0.1.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-avaria/1.0.1/pax-avaria-1.0.1-uber.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-mazovia/1.0.1/pax-mazovia-1.0.1-uber.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-novgorod/1.0.1/pax-novgorod-1.0.1-uber.jar"));
assertTrue(startup.containsKey("io/fabric8/pax-castile/1.0.1/pax-castile-1.0.1-uber.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-romana/1.0.0/pax-romana-1.0.0.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-hellenica/1.0.0/pax-hellenica-1.0.0.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-bohemia/1.0.0/pax-bohemia-1.0.0.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-pomerania/1.0.0/pax-pomerania-1.0.0.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-avaria/1.0.0/pax-avaria-1.0.0-uber.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-mazovia/1.0.0/pax-mazovia-1.0.0-uber.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-novgorod/1.0.0/pax-novgorod-1.0.0-uber.jar"));
assertFalse(startup.containsKey("io/fabric8/pax-castile/1.0.0/pax-castile-1.0.0-uber.jar"));
}
}
use of io.fabric8.patch.management.Utils.mvnurlToArtifact in project fabric8 by jboss-fuse.
the class KarafFeaturesPropertiesFileResolver method uris.
/**
* Returns a map of groupId/artifactId -> artifact
* @param uriStringsFromPatch
* @return
*/
private Map<String, Artifact> uris(List<String> uriStringsFromPatch) {
Map<String, Artifact> result = new LinkedHashMap<>();
for (String uri : uriStringsFromPatch) {
Artifact a = Utils.mvnurlToArtifact(uri, true);
if (a == null) {
continue;
}
String ga = String.format("%s/%s", a.getGroupId(), a.getArtifactId());
result.put(ga, a);
}
return result;
}
Aggregations