Search in sources :

Example 31 with GitContext

use of io.fabric8.api.GitContext in project fabric8 by jboss-fuse.

the class DummyBatchingProgressMonitor method executeInternal.

private <T> T executeInternal(GitContext context, PersonIdent personIdent, GitOperation<T> operation) {
    if (context.isRequirePull() || context.isRequireCommit()) {
        assertWriteLock();
    } else {
        assertReadLock();
    }
    // [FABRIC-887] Must set the TCCL to the classloader that loaded GitDataStore as we need the classloader
    // that could load this class, as jgit will load resources from classpath using the TCCL
    // and that requires the TCCL to the classloader that could load GitDataStore as the resources
    // jgit requires are in the same bundle as GitDataSource (eg embedded inside fabric-git)
    ClassLoader tccl = Thread.currentThread().getContextClassLoader();
    try {
        ClassLoader gitcl = GitDataStoreImpl.class.getClassLoader();
        Thread.currentThread().setContextClassLoader(gitcl);
        LOGGER.trace("Setting ThreadContextClassLoader to {} instead of {}", gitcl, tccl);
        Git git = getGit();
        Repository repository = git.getRepository();
        if (personIdent == null) {
            personIdent = new PersonIdent(repository);
        }
        if (context.isRequirePull()) {
            doPullInternal(context, getCredentialsProvider(), false, gitTimeout);
        }
        T result = operation.call(git, context);
        if (context.isRequireCommit()) {
            doCommit(git, context);
            Object cacheKey = context.getCacheKey();
            if (cacheKey == null || cacheKey.equals(GitHelpers.MASTER_BRANCH)) {
                versionCache.invalidateAll();
            } else {
                versionCache.invalidate(cacheKey);
            }
            notificationRequired = true;
        }
        if (context.isRequirePush()) {
            PushPolicyResult pushResult = doPushInternal(context, getCredentialsProvider());
            if (!pushResult.getRejectedUpdates().isEmpty()) {
                Exception gitex = pushResult.getLastException();
                throw new IllegalStateException("Push rejected: " + pushResult.getRejectedUpdates().values(), gitex);
            }
        }
        return result;
    } catch (Exception e) {
        throw FabricException.launderThrowable(e);
    } finally {
        LOGGER.trace("Restoring ThreadContextClassLoader to {}", tccl);
        Thread.currentThread().setContextClassLoader(tccl);
    }
}
Also used : Repository(org.eclipse.jgit.lib.Repository) Git(org.eclipse.jgit.api.Git) PersonIdent(org.eclipse.jgit.lib.PersonIdent) PushPolicyResult(io.fabric8.git.PullPushPolicy.PushPolicyResult) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FabricException(io.fabric8.api.FabricException) KeeperException(org.apache.zookeeper.KeeperException) MalformedURLException(java.net.MalformedURLException)

Example 32 with GitContext

use of io.fabric8.api.GitContext in project fabric8 by jboss-fuse.

the class DummyBatchingProgressMonitor method updateProfile.

@Override
public String updateProfile(GitContext context, final Profile profile, boolean force) {
    IllegalStateAssertion.assertNotNull(profile, "profile");
    LockHandle writeLock = aquireWriteLock();
    try {
        assertValid();
        // Get the existing profile
        final String versionId = profile.getVersion();
        final String profileId = profile.getId();
        final Profile lastProfile = getRequiredProfile(versionId, profileId);
        if (force || !lastProfile.equals(profile)) {
            GitOperation<String> gitop = new GitOperation<String>() {

                public String call(Git git, GitContext context) throws Exception {
                    checkoutRequiredProfileBranch(git, context, versionId, profileId);
                    return createOrUpdateProfile(context, lastProfile, profile, new HashSet<String>());
                }
            };
            return executeInternal(context, null, gitop);
        } else {
            LOGGER.debug("Skip unchanged profile update for: {}", profile);
            return lastProfile.getId();
        }
    } finally {
        writeLock.unlock();
    }
}
Also used : LockHandle(io.fabric8.api.LockHandle) Git(org.eclipse.jgit.api.Git) GitContext(io.fabric8.api.GitContext) Profile(io.fabric8.api.Profile)

Example 33 with GitContext

use of io.fabric8.api.GitContext in project fabric8 by jboss-fuse.

the class DummyBatchingProgressMonitor method deleteVersion.

@Override
public void deleteVersion(GitContext context, final String versionId) {
    IllegalStateAssertion.assertNotNull(versionId, "versionId");
    LockHandle writeLock = aquireWriteLock();
    try {
        assertValid();
        LOGGER.debug("Delete version: " + versionId);
        GitOperation<Void> gitop = new GitOperation<Void>() {

            public Void call(Git git, GitContext context) throws Exception {
                removeVersionFromCaches(versionId);
                GitHelpers.removeBranch(git, versionId);
                git.push().setTimeout(gitTimeout).setCredentialsProvider(getCredentialsProvider()).setRefSpecs(new RefSpec().setSource(null).setDestination("refs/heads/" + versionId)).call();
                return null;
            }
        };
        executeInternal(context, null, gitop);
    } finally {
        writeLock.unlock();
    }
}
Also used : LockHandle(io.fabric8.api.LockHandle) Git(org.eclipse.jgit.api.Git) RefSpec(org.eclipse.jgit.transport.RefSpec) GitContext(io.fabric8.api.GitContext)

Example 34 with GitContext

use of io.fabric8.api.GitContext in project fabric8 by jboss-fuse.

the class DummyBatchingProgressMonitor method deleteProfile.

@Override
public void deleteProfile(GitContext context, final String versionId, final String profileId) {
    IllegalStateAssertion.assertNotNull(versionId, "versionId");
    IllegalStateAssertion.assertNotNull(profileId, "profileId");
    LockHandle writeLock = aquireWriteLock();
    try {
        assertValid();
        LOGGER.debug("Delete " + ProfileBuilder.Factory.create(versionId, profileId).getProfile());
        GitOperation<Void> gitop = new GitOperation<Void>() {

            public Void call(Git git, GitContext context) throws Exception {
                checkoutRequiredProfileBranch(git, context, versionId, profileId);
                File profileDirectory = GitHelpers.getProfileDirectory(git, profileId);
                recursiveDeleteAndRemove(git, profileDirectory);
                context.commitMessage("Removed profile " + profileId);
                return null;
            }
        };
        executeInternal(context, null, gitop);
    } finally {
        writeLock.unlock();
    }
}
Also used : LockHandle(io.fabric8.api.LockHandle) Git(org.eclipse.jgit.api.Git) GitContext(io.fabric8.api.GitContext) File(java.io.File) LockFile(org.eclipse.jgit.internal.storage.file.LockFile)

Example 35 with GitContext

use of io.fabric8.api.GitContext in project fabric8 by jboss-fuse.

the class DummyBatchingProgressMonitor method activateInternal.

private void activateInternal() throws Exception {
    LOGGER.info("Starting up GitDataStore " + this);
    // Call the bootstrap {@link DataStoreTemplate}
    DataStoreTemplate template = runtimeProperties.get().removeRuntimeAttribute(DataStoreTemplate.class);
    if (template != null) {
        // Do the initial commit and set the root tag
        Ref rootTag = getGit().getRepository().getRef(GitHelpers.ROOT_TAG);
        if (rootTag == null) {
            getGit().commit().setMessage("First Commit").setCommitter("fabric", "user@fabric").call();
            getGit().tag().setName(GitHelpers.ROOT_TAG).setMessage("Tag the root commit").call();
        }
        LOGGER.debug("Running datastore bootstrap template: " + template);
        template.doWith(this, dataStore.get());
    }
    // Setup proxy service
    GitProxyService proxyService = gitProxyService.get();
    defaultProxySelector = ProxySelector.getDefault();
    // authenticator disabled, until properly tested it does not affect others, as Authenticator is static in the JVM
    // Authenticator.setDefault(new FabricGitLocalHostAuthenticator(proxyService));
    ProxySelector fabricProxySelector = new FabricGitLocalHostProxySelector(defaultProxySelector, proxyService);
    ProxySelector.setDefault(fabricProxySelector);
    LOGGER.debug("Setting up FabricProxySelector: {}", fabricProxySelector);
    if (gitRemoteUrl != null) {
        gitListener.runRemoteUrlChanged(gitRemoteUrl);
        remoteUrl = gitRemoteUrl;
    } else {
        gitService.get().addGitListener(gitListener);
        remoteUrl = gitService.get().getRemoteUrl();
        if (remoteUrl != null) {
            gitListener.runRemoteUrlChanged(remoteUrl);
        }
    }
    // Get initial versions
    getInitialVersions();
    // poll logic in case of remote git repo
    if (gitRemoteUrl != null) {
        // i need this old logic in case of remote repos
        LOGGER.info("Starting to pull from remote git repository every {} millis", gitRemotePollInterval);
        threadPool.scheduleWithFixedDelay(new Runnable() {

            @Override
            public void run() {
                LockHandle writeLock = aquireWriteLock();
                try {
                    LOGGER.trace("Performing timed pull");
                    doPullInternal();
                    LOGGER.debug("Performed timed pull from external git repo");
                } catch (Throwable e) {
                    LOGGER.debug("Error during performed timed pull/push due " + e.getMessage(), e);
                    LOGGER.warn("Error during performed timed pull/push due " + e.getMessage() + ". This exception is ignored.");
                } finally {
                    writeLock.unlock();
                }
            }

            @Override
            public String toString() {
                return "TimedPushTask";
            }
        }, 1000, gitRemotePollInterval, TimeUnit.MILLISECONDS);
    }
    LOGGER.info("Using ZooKeeper SharedCount to react when master git repo is changed, so we can do a git pull to the local git repo.");
    counter = new SharedCount(curator.get(), ZkPath.GIT_TRIGGER.getPath(), 0);
    counter.addListener(new SharedCountListener() {

        @Override
        public void countHasChanged(final SharedCountReader sharedCountReader, final int value) throws Exception {
            Runnable task = new Runnable() {

                @Override
                public void run() {
                    doPullInternal();
                }
            };
            if (gitRandomFetchDelay == 0) {
                LOGGER.debug("Watch counter updated to " + value + ", scheduling immediate pull");
                threadPool.submit(task);
            } else {
                int delay = RND.nextInt(gitRandomFetchDelay) + 1;
                LOGGER.debug("Watch counter updated to " + value + ", scheduling pull with random delay=" + delay + "s");
                threadPool.schedule(task, delay, TimeUnit.SECONDS);
            }
        }

        @Override
        public void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) {
            switch(connectionState) {
                case SUSPENDED:
                case READ_ONLY:
                case LOST:
                    // do nothing
                    break;
                case CONNECTED:
                case RECONNECTED:
                    LOGGER.info("Shared Counter (Re)connected, doing a pull");
                    doPullInternal();
                    break;
            }
        }
    });
    try {
        counter.start();
    } catch (KeeperException.NotReadOnlyException ex) {
    // In read only mode the counter is not going to start.
    // If the connection is reestablished the component will reactivate.
    // We need to catch this error so that the component gets activated.
    }
    if (gitGcOnLoad) {
        LockHandle writeLock = aquireWriteLock();
        try {
            GitOperation<Void> gitop = new GitOperation<Void>() {

                public Void call(Git git, GitContext context) throws Exception {
                    long before = System.currentTimeMillis();
                    try {
                        git.gc().call();
                        LOGGER.debug("git gc took " + ((System.currentTimeMillis() - before)) + " ms.");
                    } catch (GitAPIException e) {
                        LOGGER.debug("git gc threw an exception!", e);
                    }
                    return null;
                }
            };
            executeInternal(new GitContext(), null, gitop);
        } finally {
            writeLock.unlock();
        }
    }
    // failing to activate the component
    if (readWriteLock.isWriteLockedByCurrentThread() || readWriteLock.getWriteHoldCount() == 0) {
        try {
            // let's delegate to other thread in order to free MCF thread
            // ENTESB-7843: there's a problem when jetty is configured with TLS and keystore location using
            // profile: URI. while Jetty continues to be configured if profile:jetty.xml isn't available
            // (and it isn't initially), it fails trying to access keystore via profile: URI.
            // we should optimistically assume we can pull, but there's nothing wrong if we can't
            // - we'll be able to pull later
            threadPoolInitial.execute(new Runnable() {

                @Override
                public void run() {
                    doPullInternal(5);
                }
            });
        } catch (IllegalStateException e) {
            LOGGER.info("Another thread acquired write lock and GitDataStore can't pull from remote repository.");
        }
    } else {
        LOGGER.info("Another thread is keeping git write lock. GitDataStore will continue activation.");
    }
}
Also used : SharedCount(org.apache.curator.framework.recipes.shared.SharedCount) ProxySelector(java.net.ProxySelector) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) CuratorFramework(org.apache.curator.framework.CuratorFramework) DataStoreTemplate(io.fabric8.api.DataStoreTemplate) SharedCountListener(org.apache.curator.framework.recipes.shared.SharedCountListener) GitProxyService(io.fabric8.git.GitProxyService) LockHandle(io.fabric8.api.LockHandle) SharedCountReader(org.apache.curator.framework.recipes.shared.SharedCountReader) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FabricException(io.fabric8.api.FabricException) KeeperException(org.apache.zookeeper.KeeperException) MalformedURLException(java.net.MalformedURLException) Ref(org.eclipse.jgit.lib.Ref) Git(org.eclipse.jgit.api.Git) GitContext(io.fabric8.api.GitContext) ConnectionState(org.apache.curator.framework.state.ConnectionState) KeeperException(org.apache.zookeeper.KeeperException)

Aggregations

GitContext (io.fabric8.api.GitContext)41 Git (org.eclipse.jgit.api.Git)22 DefaultPullPushPolicy (io.fabric8.git.internal.DefaultPullPushPolicy)18 Test (org.junit.Test)18 LockHandle (io.fabric8.api.LockHandle)15 ArrayList (java.util.ArrayList)13 File (java.io.File)12 Ref (org.eclipse.jgit.lib.Ref)11 IOException (java.io.IOException)9 GitAPIException (org.eclipse.jgit.api.errors.GitAPIException)8 PushResult (org.eclipse.jgit.transport.PushResult)8 PersonIdent (org.eclipse.jgit.lib.PersonIdent)7 FabricException (io.fabric8.api.FabricException)5 Profile (io.fabric8.api.Profile)4 RevCommit (org.eclipse.jgit.revwalk.RevCommit)3 GitVersion (io.fabric8.api.commands.GitVersion)2 GitDataStore (io.fabric8.git.GitDataStore)2 GitService (io.fabric8.git.GitService)2 PushPolicyResult (io.fabric8.git.PullPushPolicy.PushPolicyResult)2 GitOperation (io.fabric8.git.internal.GitOperation)2