Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stop and remove using regex names #900

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Improve GZIP compression performance for docker:save ([#1205](https://github.com/fabric8io/docker-maven-plugin/issues/1205))
- Allow docker:save to attach image archive as a project artifact ([#1210](https://github.com/fabric8io/docker-maven-plugin/pull/1210))
- Use pattern to detect image name in archive loaded during build and tag with image name from the project configuration ([#1207](https://github.com/fabric8io/docker-maven-plugin/issues/1207))
- Stop and remove using regex names (#900)

* **0.29.0** (2019-04-08)
- Avoid failing docker:save when no images with build configuration are present ([#1185](https://github.com/fabric8io/docker-maven-plugin/issues/1185))
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/io/fabric8/maven/docker/RemoveMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
import io.fabric8.maven.docker.service.ServiceHub;
import io.fabric8.maven.docker.util.ImageName;

import java.util.List;

import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.util.Collections;
import java.util.List;

/**
* Mojo for removing images. By default only data images are removed. Data images are
Expand All @@ -52,20 +53,27 @@ public class RemoveMojo extends AbstractDockerMojo {

@Parameter(property = "docker.removeMode")
private String removeMode;

/**
* Skip building tags
*/
@Parameter(property = "docker.skip.tag", defaultValue = "false")
private boolean skipTag;

@Parameter(property = "docker.removeUsingRegex", defaultValue = "false")
private boolean removeUsingRegex;

@Override
protected void executeInternal(ServiceHub hub) throws DockerAccessException {
for (ImageConfiguration image : getResolvedImages()) {
String name = image.getName();

if (imageShouldBeRemoved(image)) {
removeImage(hub, name);
if (removeUsingRegex && image.getNameRegex() != null) {
removeWithRegexp(hub, image.getNameRegex());
} else {
removeImage(hub, name);
}

if(!skipTag) {
// Remove any tagged images
Expand Down Expand Up @@ -106,6 +114,13 @@ private void removeImage(ServiceHub hub, String name) throws DockerAccessExcepti
}
}

private void removeWithRegexp(ServiceHub hub, String nameRegexp) throws DockerAccessException {
QueryService queryService = hub.getQueryService();
for (String name : queryService.findImageNamesByRegex(nameRegexp)) {
removeImage(hub, name);
}
}

private List<String> getImageBuildTags(ImageConfiguration image){
return image.getBuildConfiguration() != null ?
image.getBuildConfiguration().getTags() :
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/io/fabric8/maven/docker/StopMojo.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package io.fabric8.maven.docker;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.fabric8.maven.docker.access.DockerAccessException;
import io.fabric8.maven.docker.access.ExecException;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.NetworkConfig;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import io.fabric8.maven.docker.log.LogDispatcher;
import io.fabric8.maven.docker.model.Container;
import io.fabric8.maven.docker.model.Network;
Expand Down Expand Up @@ -60,6 +65,9 @@ public class StopMojo extends AbstractDockerMojo {
@Parameter(property = "docker.containerNamePattern")
private String containerNamePattern = ContainerNamingUtil.DEFAULT_CONTAINER_NAME_PATTERN;

@Parameter( property = "docker.stopUsingRegex", defaultValue = "false" )
private boolean userRegexForStopping;

@Override
protected void executeInternal(ServiceHub hub) throws MojoExecutionException, IOException, ExecException {
QueryService queryService = hub.getQueryService();
Expand Down Expand Up @@ -98,6 +106,34 @@ private void stopContainers(QueryService queryService, RunService runService, Ga
runService.removeCustomNetworks(networksToRemove);
}

// If naming strategy is alias stop a container with this name, otherwise get all containers with this image's name
private List<Container> getContainersToStop(QueryService queryService, ImageConfiguration image) throws DockerAccessException {
RunImageConfiguration.NamingStrategy strategy = image.getRunConfiguration().getNamingStrategy();

if (strategy == RunImageConfiguration.NamingStrategy.alias) {
if(userRegexForStopping) {
return queryService.findContainersByRegex(image.getAliasRegex());
}
else {
Container container = queryService.getContainer(image.getAlias());
return container != null ? Collections.singletonList(container) : Collections.<Container>emptyList();
}
} else {
if(userRegexForStopping) {
List<String> imageNames = queryService.findImageNamesByRegex(image.getNameRegex());
List<Container> containers = new ArrayList<Container>();
for(String imageName : imageNames) {
List<Container> foundContainers = queryService.getContainersForImage(imageName, true);
containers.addAll(foundContainers);
}
return containers;
}
else {
return queryService.getContainersForImage(image.getName(), true);
}
}
}

private boolean shouldStopContainer(Container container, GavLabel gavLabel) {
if (isStopAllContainers()) {
return true;
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/io/fabric8/maven/docker/access/DockerAccess.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ public interface DockerAccess {
*/
ExecDetails getExecContainer(String containerIdOrName) throws DockerAccessException;

/**
* Get a container
*
* @param containerIdOrName container id or name
* @return <code>ContainerDetails<code> representing the container or null if none could be found
* @throws DockerAccessException if the container could not be inspected
*/
List<Container> findContainerByRegex(String regexContainerIdOrName) throws DockerAccessException;


/**
* Check whether the given name exists as image at the docker daemon
*
Expand All @@ -56,6 +66,13 @@ public interface DockerAccess {
*/
boolean hasImage(String name) throws DockerAccessException;

/**
* Check whether the given name exists as image at the docker daemon
*
* @param name image name to check
* @return true if the image exists
*/
List<String> findImageByRegexName(String nameRegex) throws DockerAccessException;
/**
* Get the image id of a given name or <code>null</code> if no such image exists
*
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/fabric8/maven/docker/access/UrlBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public String inspectImage(String name) {
.build();
}

public String listImages() {
return u("images/json").p("all", true)
.build();
}

public String containerLogs(String containerId, boolean follow) {
return u("containers/%s/logs", containerId)
.p("stdout",true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import java.net.URI;
import java.util.regex.Pattern;

import java.io.File;
import java.io.FileNotFoundException;
Expand All @@ -18,7 +20,6 @@
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -342,6 +343,42 @@ public ExecDetails getExecContainer(String containerIdOrName) throws DockerAcces
}
}

@Override
public List<Container> findContainerByRegex(String regexContainerIdOrName) throws DockerAccessException {
String url = urlBuilder.listContainers(true);
Pattern p = Pattern.compile(regexContainerIdOrName);
List<Container> containers = new ArrayList<>();
List<String> matchingNames = new ArrayList<>();
try {
HttpBodyAndStatus response = delegate.get(url, new BodyAndStatusResponseHandler(), HTTP_OK, HTTP_NOT_FOUND);
if (response.getStatusCode() == HTTP_NOT_FOUND) {
return containers;
} else {
JsonArray array = JsonFactory.newJsonArray(response.getBody());

for (int i = 0; i < array.size(); i++) {
JsonObject container = array.get(i).getAsJsonObject();
JsonArray names = container.get("Names").getAsJsonArray();
for(int x = 0; x < names.size(); x++) {
String name = names.get(x).getAsString();
if(name.startsWith("/")) {
name = name.substring(1);
}
if(p.matcher(name).matches()){
matchingNames.add(name);
}
}
}
for(String name : matchingNames) {
containers.add(getContainer(name));
}
return containers;
}
} catch(Exception e) {
throw new DockerAccessException(e, "Unable to list container regex for [%s]", regexContainerIdOrName);
}
}

private HttpBodyAndStatus inspectContainer(String containerIdOrName) throws DockerAccessException {
try {
String url = urlBuilder.inspectContainer(containerIdOrName);
Expand Down Expand Up @@ -613,7 +650,7 @@ public void shutdown() {
}

ApacheHttpClientDelegate createHttpClient(ClientBuilder builder) throws IOException {
return createHttpClient(builder, true);
return createHttpClient(builder, true);
}

ApacheHttpClientDelegate createHttpClient(ClientBuilder builder, boolean pooled) throws IOException {
Expand Down Expand Up @@ -726,8 +763,46 @@ public String fetchApiVersionFromServer(String baseUrl, ApacheHttpClientDelegate
get.addHeader(HttpHeaders.ACCEPT, "*/*");
get.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
try (CloseableHttpResponse response = delegate.getHttpClient().execute(get)) {

return response.getFirstHeader("Api-Version") != null ? response.getFirstHeader("Api-Version").getValue() : API_VERSION;
}
}

@Override
public List<String> findImageByRegexName(String nameRegex) throws DockerAccessException {
String url = urlBuilder.listImages();
List<String> imageNames = new ArrayList<>();
Pattern p = Pattern.compile(nameRegex);

try {
HttpBodyAndStatus response = delegate.get(url, new BodyAndStatusResponseHandler(), HTTP_OK, HTTP_NOT_FOUND);
if (response.getStatusCode() == HTTP_NOT_FOUND) {
return imageNames;
}
JsonArray imageDetails = JsonFactory.newJsonArray(response.getBody());

for(int i=0; i < imageDetails.size(); i++) {
JsonObject image = imageDetails.get(i).getAsJsonObject();
if(!image.has("RepoTags") || image.get("RepoTags").isJsonNull()) {
log.debug("Invalid RepoTags found on %s", image.get("Id"));
continue;
}
try{
JsonArray tags = image.get("RepoTags").getAsJsonArray();
for(int x=0; x < tags.size(); x++) {
String tag = tags.get(x).getAsString();
if(p.matcher(tag).matches()) {
imageNames.add(tag);
}
}
}catch(Exception ex) {
log.error("Error processing RepoTags section of %s", image.get("Id"));
ex.printStackTrace();
}
}
return imageNames;

} catch (IOException e) {
throw new DockerAccessException(e, "Unable to find name by regex [%s]", nameRegex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ public File createDockerTarArchive(String imageName, MojoParameters params, Buil
*/
public File createDockerTarArchive(String imageName, final MojoParameters params, final BuildImageConfiguration buildConfig, Logger log, ArchiverCustomizer finalCustomizer)
throws MojoExecutionException {

final BuildDirs buildDirs = createBuildDirs(imageName, params);
final AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ public class ImageConfiguration implements StartOrderResolver.Resolvable, Serial
@Parameter(required = true)
private String name;

@Parameter
private String nameRegex;

@Parameter
private String alias;

@Parameter
private String aliasRegex;

@Parameter
private RunImageConfiguration run;

Expand Down Expand Up @@ -67,7 +73,7 @@ public void setExternalConfiguration(Map<String, String> externalConfiguration)
}

@Override
public String getAlias() {
public String getAlias() {
return alias;
}

Expand Down Expand Up @@ -224,4 +230,20 @@ public Builder watchConfig(WatchImageConfiguration watchConfig) {
return this;
}
}

public String getNameRegex() {
return nameRegex;
}

public void setNameRegex(String nameRegex) {
this.nameRegex = nameRegex;
}

public String getAliasRegex() {
return aliasRegex;
}

public void setAliasRegex(String aliasRegex) {
this.aliasRegex = aliasRegex;
}
}
14 changes: 14 additions & 0 deletions src/main/java/io/fabric8/maven/docker/service/QueryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ public Container getMandatoryContainer(String containerIdOrName) throws DockerAc
return container;
}

/**
* Find containers by the given regex name
* @param nameRegex of container to lookup
* @return the List of containers found or empty List if no container is available.
* @throws DockerAccessException in case of an remote error
*/
public List<Container> findContainersByRegex(final String regexContainerIdOrName) throws DockerAccessException {
return docker.findContainerByRegex(regexContainerIdOrName);
}

public List<String> findImageNamesByRegex(String nameRegex) throws DockerAccessException {
return docker.findImageByRegexName(nameRegex);
}

/**
* Get a container running for a given container name.
* @param containerIdOrName name of container to lookup
Expand Down