From 7eb9d9f5006e43855a333a71aad355f1b09e6899 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 22 Sep 2018 11:17:14 +0100 Subject: [PATCH] Add support for exploded Boot archive in deployer --- .../src/it/support/pom.xml | 217 ++++++++++-------- .../FunctionCreatorConfiguration.java | 14 +- ...FunctionAppExplodedConfigurationTests.java | 106 +++++++++ 3 files changed, 236 insertions(+), 101 deletions(-) create mode 100644 spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/SpringFunctionAppExplodedConfigurationTests.java diff --git a/spring-cloud-function-deployer/src/it/support/pom.xml b/spring-cloud-function-deployer/src/it/support/pom.xml index 823acf6de..0eba99cc3 100644 --- a/spring-cloud-function-deployer/src/it/support/pom.xml +++ b/spring-cloud-function-deployer/src/it/support/pom.xml @@ -1,106 +1,129 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.example - function-sample - 1.0.0.M1 - jar + com.example + function-sample + 1.0.0.M1 + jar - - org.springframework.boot - spring-boot-starter-parent - 2.0.3.RELEASE - - + + org.springframework.boot + spring-boot-starter-parent + 2.0.3.RELEASE + + - - 1.8 - 2.0.0.BUILD-SNAPSHOT - 1.0.12.RELEASE - + + 1.8 + 2.0.0.BUILD-SNAPSHOT + 1.0.12.RELEASE + - - - org.springframework.cloud - spring-cloud-function-context - ${spring-cloud-function.version} - - - org.springframework.boot - spring-boot-starter - - + + + org.springframework.cloud + spring-cloud-function-context + ${spring-cloud-function.version} + + + org.springframework.boot + spring-boot-starter + + - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/release - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release-local - - false - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + exec + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + package + + unpack + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + exec + + + + + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + false + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + false + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + false + + + diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionCreatorConfiguration.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionCreatorConfiguration.java index 3b5b867b0..5ba8e8bcb 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionCreatorConfiguration.java +++ b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionCreatorConfiguration.java @@ -295,13 +295,19 @@ class FunctionCreatorConfiguration { if (!"file".equals(url.getProtocol())) { return Collections.singletonList(url); } - if (!url.toString().endsWith(".jar")) { - return Collections.singletonList(url); - } try { File file = new File(url.toURI()); if (file.exists()) { - JarFileArchive archive = new JarFileArchive(file); + Archive archive; + if (!url.toString().endsWith(".jar")) { + if (!new File(file, "BOOT-INF").exists()) { + return Collections.singletonList(url); + } + archive = new ExplodedArchive(file); + } + else { + archive = new JarFileArchive(file); + } return Arrays .asList(new ComputeLauncher(archive).getClassLoaderUrls()); } diff --git a/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/SpringFunctionAppExplodedConfigurationTests.java b/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/SpringFunctionAppExplodedConfigurationTests.java new file mode 100644 index 000000000..7926ec9ea --- /dev/null +++ b/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/SpringFunctionAppExplodedConfigurationTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2017 the original author or authors. + * + * 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. + */ + +package org.springframework.cloud.function.deployer; + +import java.util.function.Function; +import java.util.function.Supplier; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.rule.OutputCapture; +import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.containsString; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = FunctionDeployerConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) +@TestPropertySource(properties = { + "function.location=file:target/it/support/target/dependency", }) +public abstract class SpringFunctionAppExplodedConfigurationTests { + + @Autowired + protected FunctionCatalog catalog; + + @EnableAutoConfiguration + @TestPropertySource(properties = { "function.bean=myEmitter", + "function.main=com.example.functions.FunctionApp" }) + public static class SourceTests extends SpringFunctionAppExplodedConfigurationTests { + + @Test + public void test() throws Exception { + Supplier> function = catalog.lookup(Supplier.class, "function0"); + assertThat(function.get().blockFirst()).isEqualTo("one"); + } + + } + + @EnableAutoConfiguration + @TestPropertySource(properties = { "function.bean=myEmitter,myCounter" }) + public static class CompositeTests extends SpringFunctionAppExplodedConfigurationTests { + + @Test + public void test() throws Exception { + Supplier> function = catalog.lookup(Supplier.class, + "function0|function1"); + assertThat(function.get().blockFirst()).isEqualTo(3); + } + + } + + @EnableAutoConfiguration + @TestPropertySource(properties = { "function.bean=myCounter" }) + public static class ProcessorTests extends SpringFunctionAppExplodedConfigurationTests { + + @Test + public void test() throws Exception { + Function, Flux> function = catalog + .lookup(Function.class, "function0"); + assertThat(function.apply(Flux.just("spam")).blockFirst()).isEqualTo(4); + } + + } + + @EnableAutoConfiguration + @TestPropertySource(properties = { "function.bean=myDoubler" }) + public static class SinkTests extends SpringFunctionAppExplodedConfigurationTests { + + @Rule + public OutputCapture capture = new OutputCapture(); + + @Test + public void test() throws Exception { + // Can't assert side effects. + Function, Mono> function = catalog.lookup(Function.class, + "function0"); + function.apply(Flux.just(5)).block(); + capture.expect(containsString(String.format("10%n"))); + } + + } + +} \ No newline at end of file