All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jolokia.docker.maven.WatchMojo Maven / Gradle / Ivy

The newest version!
package org.jolokia.docker.maven;/*
 * 
 * Copyright 2014 Roland Huss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.StringUtils;
import org.jolokia.docker.maven.access.*;
import org.jolokia.docker.maven.assembly.AssemblyFiles;
import org.jolokia.docker.maven.config.*;
import org.jolokia.docker.maven.service.*;
import org.jolokia.docker.maven.util.MojoParameters;
import org.jolokia.docker.maven.util.StartOrderResolver;

import static org.jolokia.docker.maven.config.WatchMode.both;

/**
 * Mojo for watching source code changes.
 *
 * This Mojo does essentially
 * two things when it detects a image content change:
 *
 * 
    *
  • Rebuilding one or more images
  • *
  • Restarting restarting one or more containers
  • *
* * @goal watch * * @author roland * @since 16/06/15 */ public class WatchMojo extends AbstractBuildSupportMojo { /** @parameter property = "docker.watchMode" default-value="both" **/ private WatchMode watchMode; /** * @parameter property = "docker.watchInterval" default-value = "5000" */ private int watchInterval; /** * @parameter property = "docker.keepRunning" default-value = "false" */ private boolean keepRunning; /** * @parameter property = "docker.watchPostGoal" */ private String watchPostGoal; /** * @parameter property = "docker.watchPostExec" */ private String watchPostExec; // Scheduler private ScheduledExecutorService executor; @Override protected synchronized void executeInternal(DockerAccess dockerAccess) throws DockerAccessException, MojoExecutionException { // Important to be be a single threaded scheduler since watch jobs must run serialized executor = Executors.newSingleThreadScheduledExecutor(); QueryService queryService = serviceHub.getQueryService(); RunService runService = serviceHub.getRunService(); MojoParameters mojoParameters = createMojoParameters(); try { for (StartOrderResolver.Resolvable resolvable : runService.getImagesConfigsInOrder(queryService, getImages())) { final ImageConfiguration imageConfig = (ImageConfiguration) resolvable; String imageId = queryService.getImageId(imageConfig.getName()); String containerId = runService.lookupContainer(imageConfig.getName()); ImageWatcher watcher = new ImageWatcher(imageConfig, imageId, containerId); long interval = watcher.getInterval(); ArrayList tasks = new ArrayList<>(); if (imageConfig.getBuildConfiguration() != null && imageConfig.getBuildConfiguration().getAssemblyConfiguration() != null) { if (watcher.isCopy()) { String containerBaseDir = imageConfig.getBuildConfiguration().getAssemblyConfiguration().getBasedir(); schedule(createCopyWatchTask(dockerAccess, watcher, mojoParameters, containerBaseDir),interval); tasks.add("copying artifacts"); } if (watcher.isBuild()) { schedule(createBuildWatchTask(dockerAccess, watcher, mojoParameters, watchMode == both), interval); tasks.add("rebuilding"); } } if (watcher.isRun() && watcher.getContainerId() != null) { schedule(createRestartWatchTask(dockerAccess, watcher), interval); tasks.add("restarting"); } if (tasks.size() > 0) { log.info(imageConfig.getDescription() + ": Watch for " + StringUtils.join(tasks.toArray()," and ")); } } log.info("Waiting ..."); if (!keepRunning) { runService.addShutdownHookForStoppingContainers(keepContainer, removeVolumes); } wait(); } catch (InterruptedException e) { log.warn("Interrupted"); } finally { executor.shutdownNow(); } } private void schedule(Runnable runnable, long interval) { executor.scheduleAtFixedRate(runnable, 0, interval, TimeUnit.MILLISECONDS); } private Runnable createCopyWatchTask(final DockerAccess docker, final ImageWatcher watcher, final MojoParameters mojoParameters, final String containerBaseDir) throws MojoExecutionException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); final BuildService buildService = serviceHub.getBuildService(); final AssemblyFiles files = buildService.getAssemblyFiles(imageConfig, mojoParameters); return new Runnable() { @Override public void run() { List entries = files.getUpdatedEntriesAndRefresh(); if (entries != null && entries.size() > 0) { try { log.info(imageConfig.getDescription() + ": Assembly changed. Copying changed files to container ..."); File changedFilesArchive = buildService.createChangedFilesArchive(entries,files.getAssemblyDirectory(), imageConfig.getName(),mojoParameters); docker.copyArchive(watcher.getContainerId(), changedFilesArchive, containerBaseDir); callPostExec(serviceHub.getRunService(),watcher); } catch (MojoExecutionException | IOException e) { log.error(imageConfig.getDescription() + ": Error when copying files to container " + watcher.getContainerId() + ": " + e); } } } }; } private void callPostExec(RunService runService, ImageWatcher watcher) throws DockerAccessException { if (watcher.getPostExec() != null) { String containerId = watcher.getContainerId(); runService.execInContainer(containerId, watcher.getPostExec(), watcher.getImageConfiguration()); } } private Runnable createBuildWatchTask(final DockerAccess docker, final ImageWatcher watcher, final MojoParameters mojoParameters, final boolean doRestart) throws MojoExecutionException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); final AssemblyFiles files = serviceHub.getBuildService().getAssemblyFiles(imageConfig, mojoParameters); return new Runnable() { @Override public void run() { List entries = files.getUpdatedEntriesAndRefresh(); if (entries != null && entries.size() > 0) { try { log.info(imageConfig.getDescription() + ": Assembly changed. Rebuild ..."); buildImage(docker, imageConfig); String name = imageConfig.getName(); watcher.setImageId(serviceHub.getQueryService().getImageId(name)); if (doRestart) { restartContainer(watcher); } callPostGoal(watcher); } catch (MojoExecutionException | MojoFailureException | IOException e) { log.error(imageConfig.getDescription() + ": Error when rebuilding " + e); } } } }; } private Runnable createRestartWatchTask(final DockerAccess docker, final ImageWatcher watcher) throws DockerAccessException { final String imageName = watcher.getImageName(); return new Runnable() { @Override public void run() { try { String currentImageId = serviceHub.getQueryService().getImageId(imageName); String oldValue = watcher.getAndSetImageId(currentImageId); if (!currentImageId.equals(oldValue)) { restartContainer(watcher); callPostGoal(watcher); } } catch (DockerAccessException | MojoFailureException | MojoExecutionException e) { log.warn(watcher.getImageConfiguration().getDescription() + ": Error when restarting image " + e); } } }; } private void restartContainer(ImageWatcher watcher) throws DockerAccessException { // Stop old one RunService runService = serviceHub.getRunService(); ImageConfiguration imageConfig = watcher.getImageConfiguration(); PortMapping mappedPorts = runService.getPortMapping(imageConfig.getRunConfiguration(), project.getProperties()); String id = watcher.getContainerId(); String optionalPreStop = getPreStopCommand(imageConfig); if (optionalPreStop != null) { runService.execInContainer(id, optionalPreStop, watcher.getImageConfiguration()); } runService.stopContainer(id, false, false); // Start new one watcher.setContainerId(runService.createAndStartContainer(imageConfig, mappedPorts, project.getProperties())); } private String getPreStopCommand(ImageConfiguration imageConfig) { if (imageConfig.getRunConfiguration() != null && imageConfig.getRunConfiguration().getWaitConfiguration() != null && imageConfig.getRunConfiguration().getWaitConfiguration().getExec() != null) { return imageConfig.getRunConfiguration().getWaitConfiguration().getExec().getPreStop(); } return null; } private void callPostGoal(ImageWatcher watcher) throws MojoFailureException, MojoExecutionException { String postGoal = watcher.getPostGoal(); if (postGoal != null) { serviceHub.getMojoExecutionService().callPluginGoal(postGoal); } } // =============================================================================================================== // Helper class for holding state and parameter when watching images private class ImageWatcher { private final WatchMode mode; private final AtomicReference imageIdRef, containerIdRef; private final long interval; private final ImageConfiguration imageConfig; private final String postGoal; private String postExec; public ImageWatcher(ImageConfiguration imageConfig, String imageId, String containerIdRef) { this.imageConfig = imageConfig; this.imageIdRef = new AtomicReference<>(imageId); this.containerIdRef = new AtomicReference<>(containerIdRef); this.interval = getWatchInterval(imageConfig); this.mode = getWatchMode(imageConfig); this.postGoal = getPostGoal(imageConfig); this.postExec = getPostExec(imageConfig); } public String getContainerId() { return containerIdRef.get(); } public long getInterval() { return interval; } public String getPostGoal() { return postGoal; } public boolean isCopy() { return mode.isCopy(); } public boolean isBuild() { return mode.isBuild(); } public boolean isRun() { return mode.isRun(); } public ImageConfiguration getImageConfiguration() { return imageConfig; } public void setImageId(String imageId) { imageIdRef.set(imageId); } public void setContainerId(String containerId) { containerIdRef.set(containerId); } public String getImageName() { return imageConfig.getName(); } public String getAndSetImageId(String currentImageId) { return imageIdRef.getAndSet(currentImageId); } public String getPostExec() { return postExec; } // ========================================================= private int getWatchInterval(ImageConfiguration imageConfig) { WatchImageConfiguration watchConfig = imageConfig.getWatchConfiguration(); int interval = watchConfig != null ? watchConfig.getInterval() : WatchMojo.this.watchInterval; return interval < 100 ? 100 : interval; } private String getPostExec(ImageConfiguration imageConfig) { WatchImageConfiguration watchConfig = imageConfig.getWatchConfiguration(); return watchConfig != null && watchConfig.getPostExec() != null ? watchConfig.getPostExec() : WatchMojo.this.watchPostExec; } private String getPostGoal(ImageConfiguration imageConfig) { WatchImageConfiguration watchConfig = imageConfig.getWatchConfiguration(); return watchConfig != null && watchConfig.getPostGoal() != null ? watchConfig.getPostGoal() : WatchMojo.this.watchPostGoal; } private WatchMode getWatchMode(ImageConfiguration imageConfig) { WatchImageConfiguration watchConfig = imageConfig.getWatchConfiguration(); WatchMode mode = watchConfig != null ? watchConfig.getMode() : null; return mode != null ? mode : WatchMojo.this.watchMode; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy