Search in sources :

Example 26 with Artifact

use of io.fabric8.patch.management.Artifact in project fabric8 by jboss-fuse.

the class DeployToProfileMojoTest method before.

// Fixtures setup
@Before
public void before() {
    mojo.fabricServer = mock(Server.class);
    project = new MavenProject();
    project.setGroupId("io.fabric8");
    project.setArtifactId("artifact");
    project.setVersion(FABRIC_VERSION);
    mojo.project = project;
    deployResults = new DeployResults();
    deployResults.setProfileId("profileId");
    deployResults.setVersionId("versionId");
}
Also used : DeployResults(io.fabric8.deployer.dto.DeployResults) Server(org.apache.maven.settings.Server) MavenProject(org.apache.maven.project.MavenProject) Before(org.junit.Before)

Example 27 with Artifact

use of io.fabric8.patch.management.Artifact 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);
    }
}
Also used : Pattern(java.util.regex.Pattern) ObjectId(org.eclipse.jgit.lib.ObjectId) IOException(java.io.IOException) ListIterator(java.util.ListIterator) RevWalk(org.eclipse.jgit.revwalk.RevWalk) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) ZipArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry) DiffEntry(org.eclipse.jgit.diff.DiffEntry) Git(org.eclipse.jgit.api.Git) CherryPickResult(org.eclipse.jgit.api.CherryPickResult) RefSpec(org.eclipse.jgit.transport.RefSpec) BufferedReader(java.io.BufferedReader) StringReader(java.io.StringReader) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) PatchException(io.fabric8.patch.management.PatchException) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) Map(java.util.Map) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 28 with Artifact

use of io.fabric8.patch.management.Artifact in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method determineVersion.

/**
 * Return version of product (Fuse, Fabric8) used, but probably based on different karafHome
 * @param home
 * @param product
 * @return
 */
private String determineVersion(File home, String product) {
    if (env != EnvType.FABRIC_CHILD && env != EnvType.STANDALONE_CHILD) {
        File versions = new File(home, "fabric/import/fabric/profiles/default.profile/io.fabric8.version.properties");
        if (versions.exists() && versions.isFile()) {
            Properties props = new Properties();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(versions);
                props.load(fis);
                return props.getProperty(product);
            } catch (IOException e) {
                Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
                return null;
            } finally {
                IOUtils.closeQuietly(fis);
            }
        } else {
            Activator.log2(LogService.LOG_ERROR, "Can't find io.fabric8.version.properties file in default profile");
        }
    } else {
        // for child container we have to be more careful and not examine root container's io.fabric8.version.properties!
        File startup = new File(home, "etc/startup.properties");
        if (startup.exists() && startup.isFile()) {
            Properties props = new Properties();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(startup);
                props.load(fis);
                for (String key : props.stringPropertyNames()) {
                    if (key.startsWith("org/apache/karaf/features/org.apache.karaf.features.core")) {
                        String url = Utils.pathToMvnurl(key);
                        Artifact artifact = Utils.mvnurlToArtifact(url, true);
                        if (artifact != null) {
                            return artifact.getVersion();
                        }
                    }
                }
            } catch (IOException e) {
                Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
                return null;
            } finally {
                IOUtils.closeQuietly(fis);
            }
        } else {
            Activator.log2(LogService.LOG_ERROR, "Can't find etc/startup.properties file in child container");
        }
    }
    return null;
}
Also used : IOException(java.io.IOException) Properties(java.util.Properties) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) FileInputStream(java.io.FileInputStream) Artifact(io.fabric8.patch.management.Artifact)

Example 29 with Artifact

use of io.fabric8.patch.management.Artifact in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method uploadPatchArtifacts.

@Override
public void uploadPatchArtifacts(PatchData patchData, URI uploadAddress, UploadCallback callback) throws PatchException {
    try {
        Activator.log2(LogService.LOG_INFO, "Uploading artifacts to " + uploadAddress);
        List<File> artifacts = new LinkedList<>();
        for (String bundle : patchData.getBundles()) {
            String newUrl = Utils.mvnurlToPath(bundle);
            if (newUrl != null) {
                File repoLocation = new File(Utils.getSystemRepository(karafHome, bundleContext), newUrl);
                if (repoLocation.isFile()) {
                    artifacts.add(repoLocation);
                }
            }
        }
        for (String featureRepository : patchData.getFeatureFiles()) {
            String newUrl = Utils.mvnurlToPath(featureRepository);
            if (newUrl != null) {
                File repoLocation = new File(Utils.getSystemRepository(karafHome, bundleContext), newUrl);
                if (repoLocation.isFile()) {
                    artifacts.add(repoLocation);
                }
            }
        }
        for (String artifact : patchData.getOtherArtifacts()) {
            String newUrl = Utils.mvnurlToPath(artifact);
            if (newUrl != null) {
                File repoLocation = new File(Utils.getSystemRepository(karafHome, bundleContext), newUrl);
                if (repoLocation.isFile()) {
                    artifacts.add(repoLocation);
                }
            }
        }
        int delta = artifacts.size() / 10;
        int count = 0;
        for (File f : artifacts) {
            if (++count % delta == 0) {
                Activator.log2(LogService.LOG_DEBUG, String.format("Uploaded %d/%d", count, artifacts.size()));
            }
            String relativeName = Utils.relative(Utils.getSystemRepository(karafHome, bundleContext), f.getCanonicalFile());
            relativeName = relativeName.replace('\\', '/');
            URL uploadUrl = uploadAddress.resolve(relativeName).toURL();
            URLConnection con = uploadUrl.openConnection();
            callback.doWithUrlConnection(con);
            con.setDoInput(true);
            con.setDoOutput(true);
            con.connect();
            OutputStream os = con.getOutputStream();
            InputStream is = new FileInputStream(f);
            try {
                IOUtils.copy(is, os);
                if (con instanceof HttpURLConnection) {
                    int code = ((HttpURLConnection) con).getResponseCode();
                    if (code < 200 || code >= 300) {
                        throw new IOException("Error uploading patched artifacts: " + ((HttpURLConnection) con).getResponseMessage());
                    }
                }
            } finally {
                IOUtils.closeQuietly(is);
                IOUtils.closeQuietly(os);
            }
        }
        Activator.log2(LogService.LOG_DEBUG, String.format("Uploaded %d/%d", count, artifacts.size()));
    } catch (Exception e) {
        throw new PatchException(e.getMessage(), e);
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) JarInputStream(java.util.jar.JarInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) ByteArrayOutputStream(org.apache.commons.io.output.ByteArrayOutputStream) EOLFixingFileOutputStream(io.fabric8.patch.management.io.EOLFixingFileOutputStream) FileOutputStream(java.io.FileOutputStream) OutputStream(java.io.OutputStream) IOException(java.io.IOException) LinkedList(java.util.LinkedList) URL(java.net.URL) HttpURLConnection(java.net.HttpURLConnection) URLConnection(java.net.URLConnection) FileInputStream(java.io.FileInputStream) PatchException(io.fabric8.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) HttpURLConnection(java.net.HttpURLConnection) PatchException(io.fabric8.patch.management.PatchException) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File)

Example 30 with Artifact

use of io.fabric8.patch.management.Artifact in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method alignTo.

@Override
public boolean alignTo(Map<String, String> versions, List<String> urls, File localMavenRepository, Runnable callback) throws PatchException {
    if (aligning.getAndSet(true)) {
        return false;
    }
    try {
        if (!env.isFabric()) {
            try {
                // we probably survived fabric:create without refreshing patch-management bundle
                env = envService.determineEnvironmentType();
                File patchRepositoryLocation = new File(patchesDir, GitPatchRepositoryImpl.MAIN_GIT_REPO_LOCATION);
                getGitPatchRepository().close();
                GitPatchRepositoryImpl repository = new GitPatchRepositoryImpl(env, patchRepositoryLocation, karafHome, karafBase, karafData, patchesDir);
                setGitPatchRepository(repository);
                start();
                // let's tweak the configuration when entering fabric mode
                // this way we will track other kinds of baselines
                ensurePatchManagementInitialized();
                if (master) {
                    // let the caller know that we've configured patch management in "master" container
                    // this is mainly to push the changes from local to cluster git repository
                    // so child/ssh containers created in fabric can fetch correct baselines
                    callback.run();
                }
            } catch (Exception e) {
                throw new PatchException(e.getMessage(), e);
            }
        }
        if (env.isFabric()) {
            Git fork = null;
            try {
                ensuringLock.lock();
                String version = versions.get(env.getProductId());
                String tagName = String.format(env.getBaselineTagFormat(), version);
                // we have to be at that tag
                Git mainRepository = gitPatchRepository.findOrCreateMainGitRepository();
                fetchFabricPatchData(mainRepository);
                fork = gitPatchRepository.cloneRepository(mainRepository, true);
                gitPatchRepository.checkout(fork).setName(gitPatchRepository.getMainBranchName()).call();
                RevTag tag = gitPatchRepository.findCurrentBaseline(fork);
                if (tag != null && tagName.equals(tag.getTagName())) {
                    if (master) {
                        // and then to data/git/servlet
                        try {
                            gitPatchRepository.pushPatchBranches();
                            callback.run();
                        } catch (Exception e) {
                            Activator.log(LogService.LOG_WARNING, null, e.getMessage(), e, false);
                        } catch (Error e) {
                            // in case newer patch management calls agent which is still wired to old patch management
                            Activator.log(LogService.LOG_WARNING, null, e.getMessage(), e, false);
                        }
                    }
                    return false;
                }
                boolean baselineSwitched = handleNonCurrentBaseline(fork, version, tagName, false, true);
                if (localMavenRepository != null) {
                    try {
                        File systemRepo = getSystemRepository(karafHome, systemContext);
                        // let's copy artifacts referenced in etc/startup.properties from localMavenRepository to system
                        File etcStartupProperties = new File(karafBase, "etc/startup.properties");
                        try (FileInputStream fis = new FileInputStream(etcStartupProperties)) {
                            Properties props = new Properties();
                            props.load(fis);
                            for (String artifact : props.stringPropertyNames()) {
                                File target = new File(systemRepo, artifact);
                                File src = new File(localMavenRepository, artifact);
                                if (!target.exists() && src.isFile()) {
                                    FileUtils.copyFile(src, target);
                                }
                            }
                        }
                        // now the URLs from the passed lis
                        for (String url : urls) {
                            String path = Utils.mvnurlToPath(url);
                            if (path != null) {
                                File target = new File(systemRepo, path);
                                File src = new File(localMavenRepository, path);
                                if (!target.exists() && src.isFile()) {
                                    FileUtils.copyFile(src, target);
                                }
                            }
                        }
                    } catch (Exception e) {
                        Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, false);
                    }
                }
                return baselineSwitched;
            } catch (Exception e) {
                throw new PatchException(e.getMessage(), e);
            } finally {
                ensuringLock.unlock();
                if (fork != null) {
                    gitPatchRepository.closeRepository(fork, true);
                }
            }
        }
        return false;
    } finally {
        aligning.set(false);
    }
}
Also used : Git(org.eclipse.jgit.api.Git) RevTag(org.eclipse.jgit.revwalk.RevTag) PatchException(io.fabric8.patch.management.PatchException) Properties(java.util.Properties) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) PatchException(io.fabric8.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) FileInputStream(java.io.FileInputStream)

Aggregations

File (java.io.File)22 Artifact (io.fabric8.patch.management.Artifact)11 Test (org.junit.Test)10 IOException (java.io.IOException)9 HashMap (java.util.HashMap)8 ZipFile (org.apache.commons.compress.archivers.zip.ZipFile)8 FileInputStream (java.io.FileInputStream)6 MavenResolver (io.fabric8.maven.MavenResolver)5 PatchException (io.fabric8.patch.management.PatchException)5 ArrayList (java.util.ArrayList)5 LinkedList (java.util.LinkedList)5 FileOutputStream (java.io.FileOutputStream)4 MalformedURLException (java.net.MalformedURLException)4 Git (org.eclipse.jgit.api.Git)4 Version (org.osgi.framework.Version)4 DeployResults (io.fabric8.deployer.dto.DeployResults)3 Artifact.isSameButVersion (io.fabric8.patch.management.Artifact.isSameButVersion)3 Patch (io.fabric8.patch.management.Patch)3 Utils.mvnurlToArtifact (io.fabric8.patch.management.Utils.mvnurlToArtifact)3 HashSet (java.util.HashSet)3