diff --git a/core/src/main/java/io/fabric8/maven/core/util/DummySpringBootApplication.java b/core/src/main/java/io/fabric8/maven/core/util/DummySpringBootApplication.java new file mode 100644 index 0000000000..0076abcabb --- /dev/null +++ b/core/src/main/java/io/fabric8/maven/core/util/DummySpringBootApplication.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. + * + * Red Hat licenses this file to you 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. + */ + +package io.fabric8.maven.core.util; + +/** + * @author kameshs + */ +public class DummySpringBootApplication { + public static void main(String[] args) { + //nothing here... + } +} diff --git a/core/src/main/java/io/fabric8/maven/core/util/SpringBootUtil.java b/core/src/main/java/io/fabric8/maven/core/util/SpringBootUtil.java index 3ff090507f..f6548a3004 100644 --- a/core/src/main/java/io/fabric8/maven/core/util/SpringBootUtil.java +++ b/core/src/main/java/io/fabric8/maven/core/util/SpringBootUtil.java @@ -16,21 +16,18 @@ package io.fabric8.maven.core.util; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.SortedMap; - import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; /** * Utility methods to access spring-boot resources. @@ -39,17 +36,33 @@ public class SpringBootUtil { private static final transient Logger LOG = LoggerFactory.getLogger(SpringBootUtil.class); + /** + * This method computes the active profiles and delegate the call to the getApplicationProperties method + * + * @param project - the {@link MavenProject} + * @param activeProfiles - the comma separated String of profiles + * @return properties - the merged properties of all profiles + */ + public static Properties getApplicationProperties(MavenProject project, String activeProfiles) { + return getApplicationProperties(project, getActiveProfiles(activeProfiles)); + } + /** * Returns the spring boot configuration (supports `application.properties` and `application.yml`) * or an empty properties object if not found */ - public static Properties getSpringBootApplicationProperties(MavenProject project) { + public static Properties getApplicationProperties(MavenProject project, List activeProfiles) { URLClassLoader compileClassLoader = MavenUtil.getCompileClassLoader(project); - URL ymlResource = compileClassLoader.findResource("application.yml"); - URL propertiesResource = compileClassLoader.findResource("application.properties"); - Properties props = getPropertiesFromYamlResource(ymlResource); - props.putAll(getPropertiesResource(propertiesResource)); + Properties props = new Properties(); + addApplicationProperties(activeProfiles, compileClassLoader, props, null); + + //If the profiles are available load the profile resources as well + if (activeProfiles != null) { + for (String profile : activeProfiles) { + addApplicationProperties(activeProfiles, compileClassLoader, props, profile); + } + } return props; } @@ -68,7 +81,7 @@ public static Properties getPropertiesFile(MavenProject project, String properti protected static Properties getPropertiesResource(URL resource) { Properties answer = new Properties(); if (resource != null) { - try(InputStream stream = resource.openStream()) { + try (InputStream stream = resource.openStream()) { answer.load(stream); } catch (IOException e) { throw new IllegalStateException("Error while reading resource from URL " + resource, e); @@ -80,25 +93,79 @@ protected static Properties getPropertiesResource(URL resource) { /** * Returns a {@code Properties} representation of the given Yaml file on the project classpath if found or an empty properties object if not */ - public static Properties getPropertiesFromYamlFile(MavenProject project, String yamlFileName) { + public static Properties getPropertiesFromYamlFile(MavenProject project, String yamlFileName, + List activeProfiles) { URLClassLoader compileClassLoader = MavenUtil.getCompileClassLoader(project); URL resource = compileClassLoader.findResource(yamlFileName); - return getPropertiesFromYamlResource(resource); + return getPropertiesFromYamlResource(resource, activeProfiles); } /** * Returns a {@code Properties} representation of the given Yaml resource or an empty properties object if the resource is null */ - protected static Properties getPropertiesFromYamlResource(URL resource) { + protected static Properties getPropertiesFromYamlResource(URL resource, List activeProfiles) { if (resource != null) { try (InputStream yamlStream = resource.openStream()) { - Yaml yaml = new Yaml(); - @SuppressWarnings("unchecked") - SortedMap source = yaml.loadAs(yamlStream, SortedMap.class); + Yaml yaml = new Yaml(new SafeConstructor()); + + Map profileDocs = new HashMap<>(); + Properties properties = new Properties(); - if (source != null) { - properties.putAll(getFlattenedMap(source)); + + Iterable yamlDoc = yaml.loadAll(yamlStream); + + Iterator yamlDocIterator = yamlDoc.iterator(); + + int docCount = 0; + while (yamlDocIterator.hasNext()) { + Map docRoot = (Map) yamlDocIterator.next(); + + String profiles = null; + + if (docRoot.containsKey("spring")) { + + LinkedHashMap value = (LinkedHashMap) docRoot.get("spring"); + + Object profilesValue = value.get("profiles"); + + if (profilesValue instanceof Map) { + Map profileMap = (Map) profilesValue; + if (activeProfiles.isEmpty() && docCount > 0) { + if (profileMap.containsKey("active")) { + activeProfiles.addAll(getActiveProfiles((String) profileMap.get("active"))); + } + } + } else if (profilesValue instanceof String) { + profiles = (String) profilesValue; + } + } + + if (profiles != null) { + String[] profileSplit = profiles.split("\\s*,\\s*"); + if (!CollectionUtils. + intersection(Arrays.asList(profileSplit), activeProfiles) + .isEmpty()) { + //if the profiles is in the list of active profiles we add it to our list of docs + profileDocs.put(profiles, docRoot); + } + } else if (docCount == 0) { + //the root doc + profileDocs.put("default", docRoot); + } + + docCount++; } + + LOG.debug("Spring Boot Profile docs:{}" + profileDocs); + + properties.putAll(getFlattenedMap(profileDocs.get("default"))); + + for (String activeProfile : activeProfiles) { + if (profileDocs.containsKey(activeProfile)) { + properties.putAll(getFlattenedMap(profileDocs.get(activeProfile))); + } + } + return properties; } catch (IOException e) { throw new IllegalStateException("Error while reading Yaml resource from URL " + resource, e); @@ -117,9 +184,8 @@ public static String getSpringBootDevToolsVersion(MavenProject mavenProject) { /** * Determine the spring-boot major version for the current project */ - public static String getSpringBootVersion(MavenProject mavenProject) { - return MavenUtil.getDependencyVersion(mavenProject, SpringBootConfigurationHelper.SPRING_BOOT_GROUP_ID, SpringBootConfigurationHelper.SPRING_BOOT_ARTIFACT_ID); - } + public static String getSpringBootVersion(MavenProject mavenProject) {return MavenUtil.getDependencyVersion(mavenProject, SpringBootConfigurationHelper.SPRING_BOOT_GROUP_ID, + SpringBootConfigurationHelper.SPRING_BOOT_ARTIFACT_ID);} /** * Build a flattened representation of the Yaml tree. The conversion is compliant with the spring-boot rules. @@ -134,35 +200,81 @@ private static Map getFlattenedMap(Map source) { private static void buildFlattenedMap(Map result, Map source, String path) { for (Map.Entry entry : source.entrySet()) { String key = entry.getKey(); - if (path !=null && path.trim().length()>0) { + if (path != null && path.trim().length() > 0) { if (key.startsWith("[")) { key = path + key; - } - else { + } else { key = path + "." + key; } } Object value = entry.getValue(); if (value instanceof String) { result.put(key, value); - } - else if (value instanceof Map) { + } else if (value instanceof Map) { Map map = (Map) value; buildFlattenedMap(result, map, key); - } - else if (value instanceof Collection) { + } else if (value instanceof Collection) { Collection collection = (Collection) value; int count = 0; for (Object object : collection) { buildFlattenedMap(result, Collections.singletonMap("[" + (count++) + "]", object), key); } - } - else { + } else { result.put(key, (value != null ? value : "")); } } } + public static List getActiveProfiles(String strActiveProfiles) { + List activeProfiles = new ArrayList<>(); + if (strActiveProfiles != null) { + activeProfiles = Arrays.asList(strActiveProfiles.split("\\s*,\\s*")); + } + return activeProfiles; + } + + + /** + * Utility method to find classpath resource + * + * @param compileClassLoader - the classloader to search resource for + * @param resourceName - the name of the resource + * @return URL of the resource + */ + private static URL getResourceFromClasspath(URLClassLoader compileClassLoader, String resourceName) { + URL urlResource = compileClassLoader.findResource(resourceName); + return urlResource; + } + + /** + * Method to add the application properties from spring boot profile resources and merge them as one + * + * @param activeProfiles - the active profiles list typically a comma separated string of profile names + * @param compileClassLoader - the classloader in which the resource will be searched + * @param mergedProperties - the merged properties container + * @param profile - the profile to use when searching the spring boot resources + */ + private static void addApplicationProperties(List activeProfiles, URLClassLoader compileClassLoader, + Properties mergedProperties, String profile) { + URL ymlResource; + URL propertiesResource; + Properties profileProperties; + + if (profile == null) { + ymlResource = compileClassLoader.findResource("application.yml"); + propertiesResource = compileClassLoader.findResource("application.properties"); + mergedProperties = getPropertiesFromYamlResource(ymlResource, activeProfiles); + mergedProperties.putAll(getPropertiesResource(propertiesResource)); + } else { + ymlResource = compileClassLoader.findResource("application-" + profile + ".yml"); + profileProperties = getPropertiesFromYamlResource(ymlResource, activeProfiles); + propertiesResource = getResourceFromClasspath(compileClassLoader, + "application-" + profile + ".properties"); + profileProperties.putAll(getPropertiesResource(propertiesResource)); + mergedProperties.putAll(profileProperties); + } + } + } diff --git a/core/src/test/java/io/fabric8/maven/core/util/SpringBootUtilTest.java b/core/src/test/java/io/fabric8/maven/core/util/SpringBootUtilTest.java index 5106c40be4..18b390be44 100644 --- a/core/src/test/java/io/fabric8/maven/core/util/SpringBootUtilTest.java +++ b/core/src/test/java/io/fabric8/maven/core/util/SpringBootUtilTest.java @@ -15,7 +15,7 @@ */ package io.fabric8.maven.core.util; -import java.util.Properties; +import java.util.*; import io.fabric8.utils.PropertiesHelper; @@ -34,7 +34,8 @@ public class SpringBootUtilTest { @Test public void testYamlToPropertiesParsing() { - Properties props = SpringBootUtil.getPropertiesFromYamlResource(SpringBootUtilTest.class.getResource("/util/test-application.yml")); + Properties props = SpringBootUtil.getPropertiesFromYamlResource( + SpringBootUtilTest.class.getResource("/util/test-application.yml"), Collections.emptyList()); assertNotEquals(0, props.size()); assertEquals(new Integer(8081), PropertiesHelper.getInteger(props, "management.port")); @@ -46,10 +47,46 @@ public void testYamlToPropertiesParsing() { } + @Test + public void testYamlToPropertiesParsingWithActiveProfiles() { + + List activeProfiles = new ArrayList() {{ + add("dev"); + add("qa"); + }}; + + Properties props = SpringBootUtil.getPropertiesFromYamlResource( + SpringBootUtilTest.class.getResource("/util/test-application-multi.yml"), activeProfiles); + assertNotEquals(0, props.size()); + + assertEquals(new Integer(9090), PropertiesHelper.getInteger(props, "server.port")); + assertEquals("Hello", props.getProperty("my.name")); + assertEquals("Hola!", props.getProperty("their.name")); + } + + @Test + public void testYamlToPropertiesParsingWithActiveProfiles2() { + + List activeProfiles = new ArrayList() {{ + add("qa"); + add("dev"); + }}; + + Properties props = SpringBootUtil.getPropertiesFromYamlResource( + SpringBootUtilTest.class.getResource("/util/test-application-multi.yml"), activeProfiles); + assertNotEquals(0, props.size()); + + assertEquals(new Integer(8080), PropertiesHelper.getInteger(props, "server.port")); + assertEquals("Hello", props.getProperty("my.name")); + assertEquals("Hola!", props.getProperty("their.name")); + } + @Test public void testNonExistentYamlToPropertiesParsing() { - Properties props = SpringBootUtil.getPropertiesFromYamlResource(SpringBootUtilTest.class.getResource("/this-file-does-not-exist")); + Properties props = SpringBootUtil.getPropertiesFromYamlResource( + SpringBootUtilTest.class.getResource("/this-file-does-not-exist") + , Collections.emptyList()); assertNotNull(props); assertEquals(0, props.size()); @@ -58,7 +95,8 @@ public void testNonExistentYamlToPropertiesParsing() { @Test public void testPropertiesParsing() { - Properties props = SpringBootUtil.getPropertiesResource(SpringBootUtilTest.class.getResource("/util/test-application.properties")); + Properties props = SpringBootUtil.getPropertiesResource( + SpringBootUtilTest.class.getResource("/util/test-application.properties")); assertNotEquals(0, props.size()); assertEquals(new Integer(8081), PropertiesHelper.getInteger(props, "management.port")); diff --git a/core/src/test/resources/util/test-application-multi.yml b/core/src/test/resources/util/test-application-multi.yml new file mode 100644 index 0000000000..6efadbc32f --- /dev/null +++ b/core/src/test/resources/util/test-application-multi.yml @@ -0,0 +1,29 @@ +spring: + profiles: + active: dev,qa + +--- + +spring: + profiles: dev +server: + port: 8080 +my: + name: "Hello" + +--- + +spring: + profiles: qa +server: + port: 9090 +their: + name: "Hola!" + + +--- + +spring: + profiles: prod +server: + port: 9080 \ No newline at end of file diff --git a/enricher/fabric8/src/main/java/io/fabric8/maven/enricher/fabric8/SpringBootHealthCheckEnricher.java b/enricher/fabric8/src/main/java/io/fabric8/maven/enricher/fabric8/SpringBootHealthCheckEnricher.java index 8d68097b53..05c1d54148 100644 --- a/enricher/fabric8/src/main/java/io/fabric8/maven/enricher/fabric8/SpringBootHealthCheckEnricher.java +++ b/enricher/fabric8/src/main/java/io/fabric8/maven/enricher/fabric8/SpringBootHealthCheckEnricher.java @@ -16,8 +16,6 @@ package io.fabric8.maven.enricher.fabric8; -import java.util.Properties; - import io.fabric8.kubernetes.api.model.Probe; import io.fabric8.kubernetes.api.model.ProbeBuilder; import io.fabric8.maven.core.util.Configs; @@ -29,6 +27,7 @@ import io.fabric8.utils.PropertiesHelper; import io.fabric8.utils.Strings; +import java.util.Properties; /** * Enriches spring-boot containers with health checks if the actuator module is present. @@ -79,7 +78,11 @@ protected Probe getLivenessProbe() { protected Probe discoverSpringBootHealthCheck(Integer initialDelay, Integer period, Integer timeout) { try { if (MavenUtil.hasAllClasses(this.getProject(), REQUIRED_CLASSES)) { - Properties properties = SpringBootUtil.getSpringBootApplicationProperties(this.getProject()); + String strActiveProfiles = getContext().getConfig().getConfig("spring-boot", "activeProfiles"); + + Properties properties = SpringBootUtil.getApplicationProperties(getProject(), + strActiveProfiles); + return buildProbe(properties, initialDelay, period, timeout); } } catch (Exception ex) { diff --git a/enricher/fabric8/src/test/java/io/fabric8/maven/enricher/fabric8/AbstractSpringBootHealthCheckEnricherSupport.java b/enricher/fabric8/src/test/java/io/fabric8/maven/enricher/fabric8/AbstractSpringBootHealthCheckEnricherSupport.java index 1923c5a172..5b3828173b 100644 --- a/enricher/fabric8/src/test/java/io/fabric8/maven/enricher/fabric8/AbstractSpringBootHealthCheckEnricherSupport.java +++ b/enricher/fabric8/src/test/java/io/fabric8/maven/enricher/fabric8/AbstractSpringBootHealthCheckEnricherSupport.java @@ -379,7 +379,7 @@ public boolean hasAllClasses(MavenProject project, String ... classNames) { private void withProjectProperties(final Properties properties) { new MockUp() { @Mock - public Properties getSpringBootApplicationProperties(MavenProject project) { + public Properties getApplicationProperties(MavenProject project, String activeProfiles) { return properties; } }; diff --git a/generator/spring-boot/src/main/java/io/fabric8/maven/generator/springboot/SpringBootGenerator.java b/generator/spring-boot/src/main/java/io/fabric8/maven/generator/springboot/SpringBootGenerator.java index c78b4920a0..90a2f61990 100644 --- a/generator/spring-boot/src/main/java/io/fabric8/maven/generator/springboot/SpringBootGenerator.java +++ b/generator/spring-boot/src/main/java/io/fabric8/maven/generator/springboot/SpringBootGenerator.java @@ -33,6 +33,7 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; +import com.google.common.base.Strings; import io.fabric8.maven.core.util.Configs; import io.fabric8.maven.core.util.MavenUtil; import io.fabric8.maven.core.util.SpringBootConfigurationHelper; @@ -41,9 +42,6 @@ import io.fabric8.maven.generator.api.GeneratorContext; import io.fabric8.maven.generator.javaexec.FatJarDetector; import io.fabric8.maven.generator.javaexec.JavaExecGenerator; - -import com.google.common.base.Strings; - import org.apache.commons.io.FileUtils; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; @@ -51,6 +49,7 @@ import org.apache.maven.project.MavenProject; import static io.fabric8.maven.core.util.SpringBootConfigurationHelper.DEV_TOOLS_REMOTE_SECRET; +import static io.fabric8.maven.generator.springboot.SpringBootGenerator.Config.activeProfiles; import static io.fabric8.maven.generator.springboot.SpringBootGenerator.Config.color; /** @@ -63,9 +62,16 @@ public class SpringBootGenerator extends JavaExecGenerator { private static final String DEFAULT_SERVER_PORT = "8080"; public enum Config implements Configs.Key { - color {{ d = "false"; }}; + color {{ d = "false"; }}, + + // comma separated list of spring boot profile(s) that would be passed set as -Dspring.profiles.active + activeProfiles; + + public String def() { + return d; + } - public String def() { return d; } protected String d; + protected String d; } public SpringBootGenerator(GeneratorContext context) { @@ -75,14 +81,14 @@ public SpringBootGenerator(GeneratorContext context) { @Override public boolean isApplicable(List configs) { return shouldAddImageConfiguration(configs) - && MavenUtil.hasPlugin(getProject(), SPRING_BOOT_MAVEN_PLUGIN_GA); + && MavenUtil.hasPlugin(getProject(), SPRING_BOOT_MAVEN_PLUGIN_GA); } @Override public List customize(List configs, boolean isPrePackagePhase) throws MojoExecutionException { if (getContext().isWatchMode()) { ensureSpringDevToolSecretToken(); - if (!isPrePackagePhase ) { + if (!isPrePackagePhase) { addDevToolsFilesToFatJar(configs); } } @@ -93,8 +99,10 @@ public List customize(List configs, bool protected Map getEnv(boolean prePackagePhase) throws MojoExecutionException { Map res = super.getEnv(prePackagePhase); if (getContext().isWatchMode()) { + String strActiveProfiles = getContext().getConfig().getConfig("spring-boot", "activeProfiles"); + Properties properties = SpringBootUtil.getApplicationProperties(getProject(), strActiveProfiles); // adding dev tools token to env variables to prevent override during recompile - String secret = SpringBootUtil.getSpringBootApplicationProperties(getProject()).getProperty(SpringBootConfigurationHelper.DEV_TOOLS_REMOTE_SECRET); + String secret = properties.getProperty(SpringBootConfigurationHelper.DEV_TOOLS_REMOTE_SECRET); if (secret != null) { res.put(SpringBootConfigurationHelper.DEV_TOOLS_REMOTE_SECRET_ENV, secret); } @@ -108,6 +116,18 @@ protected List getExtraJavaOptions() { if (Boolean.parseBoolean(getConfig(color))) { opts.add("-Dspring.output.ansi.enabled=" + getConfig(color)); } + + //Spring boot active profiles + String strActiveProfiles = getConfig(activeProfiles); + if (strActiveProfiles != null) { + //String[] profiles = strActiveProfiles.split(","); + //Quoting is having issue with spring boot considering the string with quotes as profile name + //if (profiles.length > 1) { + opts.add("-Dspring.profiles.active=" + strActiveProfiles); + //} else { + // opts.add("-Dspring.profiles.active=" + strActiveProfiles); + //} + } return opts; } @@ -122,7 +142,13 @@ protected boolean isFatJar() throws MojoExecutionException { @Override protected List extractPorts() { List answer = new ArrayList<>(); - Properties properties = SpringBootUtil.getSpringBootApplicationProperties(this.getProject()); + + String strActiveProfiles = getConfig(activeProfiles); + + Properties properties = SpringBootUtil.getApplicationProperties(getContext().getProject(), + SpringBootUtil.getActiveProfiles(strActiveProfiles)); + + //TODO SK - do we need to handle the parsin of port properties like ${PORT:1234} SpringBootConfigurationHelper propertyHelper = new SpringBootConfigurationHelper(SpringBootUtil.getSpringBootVersion(getProject())); String port = properties.getProperty(propertyHelper.getServerPortPropertyKey(), DEFAULT_SERVER_PORT); addPortIfValid(answer, getConfig(JavaExecGenerator.Config.webPort, port)); @@ -134,7 +160,10 @@ protected List extractPorts() { // ============================================================================= private void ensureSpringDevToolSecretToken() throws MojoExecutionException { - Properties properties = SpringBootUtil.getSpringBootApplicationProperties(getProject()); + String strActiveProfiles = getConfig(activeProfiles); + + Properties properties = SpringBootUtil.getApplicationProperties(getContext().getProject(), + SpringBootUtil.getActiveProfiles(strActiveProfiles)); String remoteSecret = properties.getProperty(DEV_TOOLS_REMOTE_SECRET); if (Strings.isNullOrEmpty(remoteSecret)) { addSecretTokenToApplicationProperties(); @@ -177,7 +206,7 @@ private void copyFilesToFatJar(List libs, List classes, File target) continue; } out.putNextEntry(ze); - for(int read = zin.read(buffer); read > -1; read = zin.read(buffer)){ + for (int read = zin.read(buffer); read > -1; read = zin.read(buffer)) { out.write(buffer, 0, read); } out.closeEntry(); @@ -253,9 +282,9 @@ private void addSecretTokenToApplicationProperties() throws MojoExecutionExcepti File file = new File(getProject().getBasedir(), "target/classes/application.properties"); file.getParentFile().mkdirs(); String text = String.format("%s" + - "# Remote secret added by fabric8-maven-plugin\n" + - "%s=%s\n", - file.exists() ? "\n" : "", DEV_TOOLS_REMOTE_SECRET, newToken); + "# Remote secret added by fabric8-maven-plugin\n" + + "%s=%s\n", + file.exists() ? "\n" : "", DEV_TOOLS_REMOTE_SECRET, newToken); try (FileWriter writer = new FileWriter(file, true)) { writer.append(text); diff --git a/generator/spring-boot/src/test/java/io/fabric8/maven/generator/springboot/SpringBootGeneratorTest.java b/generator/spring-boot/src/test/java/io/fabric8/maven/generator/springboot/SpringBootGeneratorTest.java index 65ec79c0fc..e4b2b3ec9a 100644 --- a/generator/spring-boot/src/test/java/io/fabric8/maven/generator/springboot/SpringBootGeneratorTest.java +++ b/generator/spring-boot/src/test/java/io/fabric8/maven/generator/springboot/SpringBootGeneratorTest.java @@ -23,23 +23,23 @@ import java.util.List; import java.util.Map; +import io.fabric8.maven.core.config.ProcessorConfig; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.generator.api.GeneratorContext; - +import mockit.Expectations; +import mockit.Mocked; +import mockit.integration.junit4.JMockit; import org.apache.maven.model.Build; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.junit.Test; import org.junit.runner.RunWith; -import mockit.Expectations; -import mockit.Mocked; -import mockit.integration.junit4.JMockit; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; /** * @author roland @@ -57,6 +57,9 @@ public class SpringBootGeneratorTest { @Mocked private Build build; + @Mocked + private ProcessorConfig config; + @Test public void notApplicable() throws IOException { SpringBootGenerator generator = new SpringBootGenerator(createGeneratorContext()); @@ -76,6 +79,37 @@ public void javaOptions() throws IOException, MojoExecutionException { assertNull(env.get("JAVA_OPTIONS")); } + @Test + public void javaOptionsWithActiveProfiles() throws IOException, MojoExecutionException { + SpringBootGenerator generator = new SpringBootGenerator(createGeneratorWithActiveProfilesConfig()); + List extraOpts = generator.getExtraJavaOptions(); + assertNotNull(extraOpts); + assertEquals(1, extraOpts.size()); + + List configs = generator.customize(new ArrayList(), true); + assertEquals(1, configs.size()); + Map env = configs.get(0).getBuildConfiguration().getEnv(); + String javaOptions = env.get("JAVA_OPTIONS"); + assertNotNull(javaOptions); + assertTrue(javaOptions.equals("-Dspring.profiles.active=dev,qa")); + } + + @Test + public void javaOptionsWithActiveProfileWithSpaces() throws IOException, MojoExecutionException { + SpringBootGenerator generator = new SpringBootGenerator(createGeneratorWithActiveProfilesWithSpacesConfig()); + List extraOpts = generator.getExtraJavaOptions(); + assertNotNull(extraOpts); + assertEquals(1, extraOpts.size()); + + List configs = generator.customize(new ArrayList(), true); + assertEquals(1, configs.size()); + Map env = configs.get(0).getBuildConfiguration().getEnv(); + String javaOptions = env.get("JAVA_OPTIONS"); + assertNotNull(javaOptions); + assertTrue(javaOptions.equals("-Dspring.profiles.active=dev, qa")); + } + + private GeneratorContext createGeneratorContext() throws IOException { new Expectations() {{ context.getProject(); result = project; @@ -86,7 +120,43 @@ private GeneratorContext createGeneratorContext() throws IOException { build.getDirectory(); result = tempDir; build.getOutputDirectory(); result = tempDir; project.getPlugin(anyString); result = null; - project.getVersion(); result = "1.0.0"; minTimes = 0; + project.getVersion(); result = "1.0.0"; + minTimes = 0; + }}; + return context; + } + + private GeneratorContext createGeneratorWithActiveProfilesConfig() throws IOException { + new Expectations() {{ + context.getProject(); result = project; + project.getBuild(); result = build; + String tempDir = Files.createTempDirectory("springboot-test-project").toFile().getAbsolutePath(); + + + build.getDirectory(); result = tempDir; + build.getOutputDirectory(); result = tempDir; + project.getPlugin(anyString); result = null; + project.getVersion(); result = "1.0.0"; + minTimes = 0; + context.getConfig(); result = config; + config.getConfig("spring-boot", "activeProfiles"); result = "dev,qa"; + }}; + return context; + } + + private GeneratorContext createGeneratorWithActiveProfilesWithSpacesConfig() throws IOException { + new Expectations() {{ + context.getProject(); result = project; + project.getBuild(); result = build; + String tempDir = Files.createTempDirectory("springboot-test-project").toFile().getAbsolutePath(); + + build.getDirectory(); result = tempDir; + build.getOutputDirectory(); result = tempDir; + project.getPlugin(anyString); result = null; + project.getVersion(); result = "1.0.0"; + minTimes = 0; + context.getConfig(); result = config; + config.getConfig("spring-boot", "activeProfiles"); result = "dev, qa"; }}; return context; } diff --git a/watcher/standard/src/main/java/io/fabric8/maven/watcher/standard/SpringBootWatcher.java b/watcher/standard/src/main/java/io/fabric8/maven/watcher/standard/SpringBootWatcher.java index cf0472f95f..708c16533d 100644 --- a/watcher/standard/src/main/java/io/fabric8/maven/watcher/standard/SpringBootWatcher.java +++ b/watcher/standard/src/main/java/io/fabric8/maven/watcher/standard/SpringBootWatcher.java @@ -39,7 +39,6 @@ import io.fabric8.utils.Closeables; import io.fabric8.utils.PropertiesHelper; import io.fabric8.utils.Strings; - import org.apache.maven.project.MavenProject; import static io.fabric8.maven.core.util.SpringBootConfigurationHelper.DEV_TOOLS_REMOTE_SECRET; @@ -54,9 +53,15 @@ public class SpringBootWatcher extends BaseWatcher { private enum Config implements Configs.Key { // The time to wait for the service to be exposed (by the expose controller) - serviceUrlWaitTimeSeconds {{ d = "5"; }}; + serviceUrlWaitTimeSeconds {{ + d = "5"; + }}; + + public String def() { + return d; + } - public String def() { return d; } protected String d; + protected String d; } public SpringBootWatcher(WatcherContext watcherContext) { @@ -99,7 +104,8 @@ private String getPortForwardUrl(final Set resources) throws Except return null; } - Properties properties = SpringBootUtil.getSpringBootApplicationProperties(getContext().getProject()); + String strActiveProfiles = getContext().getConfig().getConfig("spring-boot", "activeProfiles"); + Properties properties = SpringBootUtil.getApplicationProperties(getContext().getProject(), strActiveProfiles); SpringBootConfigurationHelper propertyHelper = new SpringBootConfigurationHelper(SpringBootUtil.getSpringBootVersion(getContext().getProject())); PortForwardService portForwardService = getContext().getFabric8ServiceHub().getPortForwardService(); @@ -165,7 +171,9 @@ private boolean isExposeService(Service service) { private void runRemoteSpringApplication(String url) { log.info("Running RemoteSpringApplication against endpoint: " + url); - Properties properties = SpringBootUtil.getSpringBootApplicationProperties(getContext().getProject()); + String strActiveProfiles = getContext().getConfig().getConfig("spring-boot", "activeProfiles"); + Properties properties = SpringBootUtil.getApplicationProperties(getContext().getProject(), strActiveProfiles); + String remoteSecret = properties.getProperty(DEV_TOOLS_REMOTE_SECRET, System.getProperty(DEV_TOOLS_REMOTE_SECRET)); if (Strings.isNullOrBlank(remoteSecret)) { log.warn("There is no `%s` property defined in your src/main/resources/application.properties. Please add one!", DEV_TOOLS_REMOTE_SECRET);