diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/DockerBuildException.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/DockerBuildException.java new file mode 100644 index 000000000..314928bc0 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/DockerBuildException.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2020 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.dash.docker.exceptions; + +import org.springframework.ide.eclipse.boot.dash.api.AppConsole; + +public class DockerBuildException extends Exception { + + private static final long serialVersionUID = 1L; + + public DockerBuildException(String string) { + super(string); + } + + public void writeDetailedExplanation(AppConsole console) throws Exception { + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildScriptException.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildScriptException.java new file mode 100644 index 000000000..b3c37b6e0 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildScriptException.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2020 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.dash.docker.exceptions; + +import java.io.File; +import java.util.List; + +import org.springframework.ide.eclipse.boot.dash.api.AppConsole; +import org.springframework.ide.eclipse.boot.dash.console.LogType; + +/** + * Exception raised when BootDash wants to build a docker image but can not + * find / determine how to build it. I.e. we are looking for a number of + * different build scripts in project-relative locations. If none of + * them are found then this exception is raised. + */ +public class MissingBuildScriptException extends DockerBuildException { + + private static final long serialVersionUID = 1L; + + public final List locationsChecked; + + public MissingBuildScriptException(List locationsChecked) { + super("Neither maven wrapper, gradle wrapper or custom build script found."); + this.locationsChecked = locationsChecked; + } + + @Override + public void writeDetailedExplanation(AppConsole console) throws Exception { + console.write("Places we looked for build script: ", LogType.STDERROR); + for (File loc : this.locationsChecked) { + console.write(" - "+loc, LogType.STDERROR); + } + showBuildScriptHelp(console); + } + + private void showBuildScriptHelp(AppConsole console) { + String[] help = { + "To build a docker image, Boot Dash needs to run a build script from your project.", + "Three different types are supported and checked for in this order:", + "", + "1. "+this.locationsChecked.get(0).getAbsoluteFile().getName(), + " A custom script placed by you at the project root.", + " Typically this runs a custom maven or gradle command on your project.", + "", + "2. maven", + " If your project has a mvnw, we will use that to execute the `spring-boot:build-image` task", + "", + "3. gradle", + " If your project has a gradlew, we will use that to execute the `bootBuildImage` task", + }; + try { + for (String line : help) { + console.write(line, LogType.STDERROR); + } + } catch (Exception e1) { + //ignore + } + } + + + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildTagException.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildTagException.java new file mode 100644 index 000000000..0699ffd09 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/exceptions/MissingBuildTagException.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2020 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.dash.docker.exceptions; + +import java.util.regex.Pattern; + +import org.springframework.ide.eclipse.boot.dash.api.AppConsole; +import org.springframework.ide.eclipse.boot.dash.console.LogType; + +public class MissingBuildTagException extends DockerBuildException { + + private static final long serialVersionUID = 1L; + + public final Pattern[] whatWeLookedFor; + + public MissingBuildTagException(Pattern... whatWeLookedFor) { + super("Couldn't detect the image id or tag"); + this.whatWeLookedFor = whatWeLookedFor; + } + + @Override + public void writeDetailedExplanation(AppConsole console) throws Exception { + console.write("We detect the image tag or hash by matching specific regexp patterns", LogType.STDERROR); + console.write("in the build output. But none of the patterns we look for where found.", LogType.STDERROR); + console.write("", LogType.STDERROR); + console.write("These are the patterns that we looked for:", LogType.STDERROR); + console.write("", LogType.STDERROR); + for (Pattern pattern : whatWeLookedFor) { + console.write(" regexp: /"+pattern+"/", LogType.STDERROR); + } + } + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java index cb24411f4..031eb8db0 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java @@ -23,7 +23,6 @@ import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,6 +48,9 @@ import org.springframework.ide.eclipse.boot.dash.api.SystemPropertySupport; import org.springframework.ide.eclipse.boot.dash.api.TemporalBoolean; import org.springframework.ide.eclipse.boot.dash.console.LogType; import org.springframework.ide.eclipse.boot.dash.devtools.DevtoolsUtil; +import org.springframework.ide.eclipse.boot.dash.docker.exceptions.DockerBuildException; +import org.springframework.ide.eclipse.boot.dash.docker.exceptions.MissingBuildScriptException; +import org.springframework.ide.eclipse.boot.dash.docker.exceptions.MissingBuildTagException; import org.springframework.ide.eclipse.boot.dash.docker.jmx.JmxSupport; import org.springframework.ide.eclipse.boot.dash.docker.runtarget.BuildScriptLocator.BuildKind; import org.springframework.ide.eclipse.boot.dash.labels.BootDashLabels; @@ -70,6 +72,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectImageResponse; import com.github.dockerjava.api.exception.NotModifiedException; import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.ExposedPort; @@ -246,46 +249,17 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, return build(console); } catch (Exception e) { console.write(ExceptionUtil.getMessage(e), LogType.STDERROR); - if (e instanceof MissingBuildScriptException) { - console.write("Places we looked for build script: ", LogType.STDERROR); - for (File loc : ((MissingBuildScriptException) e).locationsChecked) { - console.write(" - "+loc, LogType.STDERROR); - } - showBuildScriptHelp(console, (MissingBuildScriptException) e); + if (e instanceof DockerBuildException) { + ((DockerBuildException) e).writeDetailedExplanation(console); } throw e; } }); - refreshTracker.run("Starting container '" + image + "'" + + BootDashLabels.ELLIPSIS, () -> { run(console, image, deployment); }); } - private void showBuildScriptHelp(AppConsole console, MissingBuildScriptException e) { - String[] help = { - "To build a docker image, Boot Dash needs to run a build script from your project.", - "Three different types are supported and checked for in this order:", - "", - "1. "+e.locationsChecked.get(0).getAbsoluteFile().getName(), - " A custom script placed by you at the project root.", - " Typically this runs a custom maven or gradle command on your project.", - "", - "2. maven", - " If your project has a mvnw, we will use that to execute the `spring-boot:build-image` task", - "", - "3. gradle", - " If your project has a gradlew, we will use that to execute the `bootBuildImage` task", - }; - try { - for (String line : help) { - console.write(line, LogType.STDERROR); - } - } catch (Exception e1) { - //ignore - } - } - private void run(AppConsole console, String image, DockerDeployment deployment) throws Exception { if (client==null) { console.write("Cannot start container... Docker client is disconnected!", LogType.STDERROR); @@ -395,11 +369,24 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, containerLogConnection.setValue(DockerContainer.connectLog(target, c.getId(), console, true)); } } + + /* Sample output from `docker build -t fui .` +Successfully built f3157a980fd2 +Successfully tagged fui:latest + */ - private static final Pattern BUILT_IMAGE_MESSAGE = Pattern.compile("Successfully built image.*\\'(.*)\\'"); + /** + * List of patterns that we look for in order of priority. If more than one pattern matches, the first pattern + * takes in this list takes priority over the next. + */ + private static final Pattern[] BUILT_IMAGE_MESSAGE_PATS = { + Pattern.compile("Successfully built image.*\\'(.*)\\'"), //from mvn spring-boot:build-image + Pattern.compile("Successfully tagged ([^\\s]+)"), //from `docker build -t .` + Pattern.compile("Successfully built ([a-f0-9]+)"), //from `docker build .` + }; private String build(AppConsole console) throws Exception { - AtomicReference image = new AtomicReference<>(); + String[] imageIds = new String[BUILT_IMAGE_MESSAGE_PATS.length]; File directory = new File(project.getLocation().toString()); String[] command = getBuildCommand(directory); @@ -412,9 +399,11 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, Process process = builder.start(); LineBasedStreamGobler outputGobler = new LineBasedStreamGobler(process.getInputStream(), (line) -> { System.out.println(line); - Matcher matcher = BUILT_IMAGE_MESSAGE.matcher(line); - if (matcher.find()) { - image.set(matcher.group(1)); + for (int i = 0; i < BUILT_IMAGE_MESSAGE_PATS.length; i++) { + Matcher matcher = BUILT_IMAGE_MESSAGE_PATS[i].matcher(line); + if (matcher.find()) { + imageIds[i] = matcher.group(1); + } } try { console.write(line, LogType.APP_OUT); @@ -435,16 +424,29 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, } outputGobler.join(); - String imageTag = image.get(); + String imageTag = null; + for (String found : imageIds) { + if (found!=null) { + imageTag = found; + break; + } + } + if (imageTag==null) { + throw new MissingBuildTagException(BUILT_IMAGE_MESSAGE_PATS); + } if (imageTag.startsWith(DOCKER_IO_LIBRARY)) { imageTag = imageTag.substring(DOCKER_IO_LIBRARY.length()); } List images = client.listImagesCmd().withImageNameFilter(imageTag).exec(); - - for (Image img : images) { - addPersistedImage(img.getId()); + if (images.isEmpty()) { + // maybe the 'imageTag' is not actually a tag but an id/hash. + InspectImageResponse inspect = client.inspectImageCmd(imageTag).exec(); + addPersistedImage(inspect.getId()); + } else { + for (Image img : images) { + addPersistedImage(img.getId()); + } } - return imageTag; } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerContainer.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerContainer.java index f9bd069f1..ff48dc29e 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerContainer.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerContainer.java @@ -100,11 +100,16 @@ public class DockerContainer implements App, RunStateProvider, JmxConnectable, S return Suppliers.memoize(() ->{ Map labels = labelsSupplier.get(); try { - Map bpmd = new ObjectMapper().readValue(labels.get("io.buildpacks.build.metadata"), Map.class); - Set deps = dependencyNamePath - .traverseAmbiguously(YamlNavigable.javaObject(bpmd)) - .flatMap(JavaObjectNav::asStringMaybe).collect(Collectors.toSet()); - return deps.contains("spring-boot-devtools"); + if (labels!=null) { + String buildpackMetadata = labels.get("io.buildpacks.build.metadata"); + if (buildpackMetadata!=null) { + Map bpmd = new ObjectMapper().readValue(buildpackMetadata, Map.class); + Set deps = dependencyNamePath + .traverseAmbiguously(YamlNavigable.javaObject(bpmd)) + .flatMap(JavaObjectNav::asStringMaybe).collect(Collectors.toSet()); + return deps.contains("spring-boot-devtools"); + } + } } catch (Exception e) { Log.log(e); } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java index a33fdaee5..62fa019a0 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java @@ -62,7 +62,6 @@ public class FakeDockerRunCommand { bindTo.getHostIp()+":"+bindTo.getHostPortSpec()+":"+exposed.getPort()+"/"+exposed.getProtocol() ); } - System.out.println(entry); } } } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/MissingBuildScriptException.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/MissingBuildScriptException.java deleted file mode 100644 index aaae5344a..000000000 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/MissingBuildScriptException.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2020 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ -package org.springframework.ide.eclipse.boot.dash.docker.runtarget; - -import java.io.File; -import java.util.List; - -/** - * Exception raised when BootDash wants to build a docker image but can not - * find / determine how to build it. I.e. we are looking for a number of - * different build scripts in project-relative locations. If none of - * them are found then this exception is raised. - */ -public class MissingBuildScriptException extends Exception { - - private static final long serialVersionUID = 1L; - - public final List locationsChecked; - - public MissingBuildScriptException(List locationsChecked) { - super("Niether maven wraper, gradle wrapper or custom build script found."); - this.locationsChecked = locationsChecked; - } - -} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/src/org/springframework/ide/eclipse/boot/dash/test/BootDashDockerTests.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/src/org/springframework/ide/eclipse/boot/dash/test/BootDashDockerTests.java index 2cc4398ce..402abfbee 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/src/org/springframework/ide/eclipse/boot/dash/test/BootDashDockerTests.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/src/org/springframework/ide/eclipse/boot/dash/test/BootDashDockerTests.java @@ -16,6 +16,9 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -26,8 +29,6 @@ import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.assert import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.assertNotContains; import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.createFile; -import static org.mockito.ArgumentMatchers.*; - import java.net.URI; import java.time.Duration; import java.util.ArrayList; @@ -53,7 +54,6 @@ import org.eclipse.swt.graphics.Color; import org.junit.After; import org.junit.Rule; import org.junit.Test; -import org.mockito.ArgumentMatchers; import org.mockito.Matchers; import org.mockito.Mockito; import org.springframework.ide.eclipse.beans.ui.live.model.LiveBeansModel; @@ -77,6 +77,7 @@ import org.springframework.ide.eclipse.boot.dash.model.BootDashElement; import org.springframework.ide.eclipse.boot.dash.model.BootDashModel; import org.springframework.ide.eclipse.boot.dash.model.BootProjectDashElement; import org.springframework.ide.eclipse.boot.dash.model.Failable; +import org.springframework.ide.eclipse.boot.dash.model.RefreshState; import org.springframework.ide.eclipse.boot.dash.model.RunState; import org.springframework.ide.eclipse.boot.dash.model.Taggable; import org.springframework.ide.eclipse.boot.dash.model.actuator.RequestMapping; @@ -100,15 +101,17 @@ import org.springframework.ide.eclipse.boot.test.BootProjectTestHarness; import org.springframework.ide.eclipse.boot.test.util.TestBracketter; import org.springsource.ide.eclipse.commons.core.util.StringUtil; import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition; +import org.springsource.ide.eclipse.commons.tests.util.StsTestCase; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerjava.api.command.InspectImageResponse; import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.Image; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.*; + public class BootDashDockerTests { private static final int BUILD_IMAGE_TIMEOUT = 30_000; @@ -122,6 +125,90 @@ public class BootDashDockerTests { createDockerTarget(); } + @Test + public void projectWithdDockerFile() throws Exception { + GenericRemoteBootDashModel model = createDockerTarget(); + IProject project = projects.createBootWebProject("webby", bootVersionAtLeast("2.3.0")); + createExeFile(project, "sts-docker-build.sh", + "#!/bin/bash\n" + + "docker build -t webby ." + ); + createFile(project, "Dockerfile", + "FROM openjdk:11 as builder\n" + + "CMD mkdir /source\n" + + "COPY . /source\n" + + "WORKDIR /source\n" + + "RUN ls -la\n" + + "RUN ./mvnw clean package\n" + + "FROM openjdk:11\n" + + "COPY --from=builder /source/target/*.jar /app.jar\n" + + "ENTRYPOINT java $JAVA_OPTS -jar /app.jar" + ); + + dragAndDrop(project, model); + GenericRemoteAppElement dep = waitForDeployment(model, project); + GenericRemoteAppElement img = waitForChild(dep, d -> d instanceof DockerImage); + GenericRemoteAppElement con = waitForChild(img, d -> d instanceof DockerContainer); + + assertContains("webby:latest", img.getStyledName(null).getString()); + + ACondition.waitFor("all started", BUILD_IMAGE_TIMEOUT, () -> { + assertEquals(RunState.RUNNING, dep.getRunState()); + assertEquals(RunState.RUNNING, img.getRunState()); + assertEquals(RunState.RUNNING, con.getRunState()); + }); + } + + + @Test + public void missingBuildTagException() throws Exception { + GenericRemoteBootDashModel model = createDockerTarget(); + IProject project = projects.createBootWebProject("webby", bootVersionAtLeast("2.3.0")); + createExeFile(project, "sts-docker-build.sh", + "#!/bin/bash\n" + + "# do nothing" + ); + dragAndDrop(project, model); + GenericRemoteAppElement dep = waitForDeployment(model, project); + ACondition.waitFor("error marker", 3_000, () -> { + RefreshState s = dep.getRefreshState(); + assertTrue(s.isError()); + assertEquals("MissingBuildTagException: Couldn't detect the image id or tag", s.getMessage()); + }); + } + + @Test + public void projectWithdDockerFileNoTag() throws Exception { + GenericRemoteBootDashModel model = createDockerTarget(); + IProject project = projects.createBootWebProject("webby", bootVersionAtLeast("2.3.0")); + createExeFile(project, "sts-docker-build.sh", + "#!/bin/bash\n" + + "docker build ." + ); + createFile(project, "Dockerfile", + "FROM openjdk:11 as builder\n" + + "CMD mkdir /source\n" + + "COPY . /source\n" + + "WORKDIR /source\n" + + "RUN ls -la\n" + + "RUN ./mvnw clean package\n" + + "FROM openjdk:11\n" + + "COPY --from=builder /source/target/*.jar /app.jar\n" + + "ENTRYPOINT java $JAVA_OPTS -jar /app.jar" + ); + + dragAndDrop(project, model); + GenericRemoteAppElement dep = waitForDeployment(model, project); + GenericRemoteAppElement img = waitForChild(dep, d -> d instanceof DockerImage); + GenericRemoteAppElement con = waitForChild(img, d -> d instanceof DockerContainer); + + ACondition.waitFor("all started", BUILD_IMAGE_TIMEOUT, () -> { + assertEquals(RunState.RUNNING, dep.getRunState()); + assertEquals(RunState.RUNNING, img.getRunState()); + assertEquals(RunState.RUNNING, con.getRunState()); + }); + } + @Test public void devtoolsFullScenario() throws Exception { GenericRemoteBootDashModel model = createDockerTarget(); diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/.project b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/.project index 580d22af2..90ac8418d 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/.project +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls.feature/.project @@ -7,6 +7,5 @@ - org.eclipse.m2e.core.maven2Nature diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/src/org/springsource/ide/eclipse/commons/tests/util/StsTestCase.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/src/org/springsource/ide/eclipse/commons/tests/util/StsTestCase.java index e00032ddd..75dffcf85 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/src/org/springsource/ide/eclipse/commons/tests/util/StsTestCase.java +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.tests.util/src/org/springsource/ide/eclipse/commons/tests/util/StsTestCase.java @@ -25,6 +25,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; @@ -125,6 +126,14 @@ public abstract class StsTestCase extends TestCase { return file; } + public static IFile createExeFile(IProject project, String path, String data) throws CoreException { + IFile f = createFile(project, path, data); + ResourceAttributes a = f.getResourceAttributes(); + a.setExecutable(true); + f.setResourceAttributes(a); + return f; + } + public static void fileReplace(IProject project, String path, String find, String replace) throws Exception { IFile file = project.getFile(path); assertTrue(file.exists()); @@ -156,4 +165,5 @@ public abstract class StsTestCase extends TestCase { fail("Found: "+needle+"\n in \n"+haystack); } } + }