introduce an optional maven plugin to update the sam config

rename module to amazon-lambda-http
This commit is contained in:
Justin Lee
2019-10-18 19:46:14 -04:00
parent 8f9617e6f0
commit e0ded23b4d
38 changed files with 628 additions and 289 deletions

6
.gitignore vendored
View File

@@ -31,8 +31,4 @@ build
docker/distroless/bazel-*
/.apt_generated_tests/
quarkus.log
replay_*.log
/docs/src/main/asciidoc/generated/
replay_*.logß

View File

@@ -408,7 +408,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam-deployment</artifactId>
<artifactId>quarkus-amazon-lambda-http-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@@ -622,12 +622,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-resteasy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam-parent</artifactId>
<artifactId>quarkus-amazon-lambda-http-parent</artifactId>
<version>999-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>quarkus-amazon-sam-deployment</artifactId>
<name>Quarkus - Amazon SAM - Deployment</name>
<artifactId>quarkus-amazon-lambda-http-deployment</artifactId>
<name>Quarkus - Amazon Lambda HTTP - Deployment</name>
<dependencies>
<dependency>
@@ -29,11 +29,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
</dependencies>
<build>

View File

@@ -0,0 +1,13 @@
package io.quarkus.amazon.lambda.http.deployment;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem;
public class AmazonLambdaHttpProcessor {
@BuildStep
public RequireVirtualHttpBuildItem requestVirtualHttp(LaunchModeBuildItem launchMode) {
return launchMode.getLaunchMode() == LaunchMode.NORMAL ? RequireVirtualHttpBuildItem.MARKER : null;
}
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-http-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-amazon-lambda-http-maven</artifactId>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,116 @@
package io.quarkus.amazon.lambda.http;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
@Mojo(name = "configure-aws-lambda", requiresProject = false)
public class AmazonLambdaHttpMojo extends AbstractMojo {
public static final String SAM_HANDLER = HttpHandler.class.getName() + "::handleRequest";
public static final String SAM_RUNTIME = "java8";
public static final String SAM_TEMPLATE = "quarkus.amazon-lambda-http.template";
public static final String SAM_RESOURCE = "quarkus.amazon-lambda-http.resource-name";
public static final String DEFAULT_TEMPLATE = "template.yaml";
public static final String DEFAULT_RESOURCE = "Quarkus";
@Parameter(defaultValue = "${project}")
protected MavenProject project;
@Parameter(property = "sam.template", defaultValue = DEFAULT_TEMPLATE)
private String templateFile;
@Parameter(property = "sam.resource", defaultValue = DEFAULT_RESOURCE)
private String resourceName;
@SuppressWarnings("unchecked")
@Override
public void execute() {
try {
System.out.println("******************* AmazonLambdaHttpMojo.execute");
final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Properties application = new Properties();
File appProperties = new File("src/main/resources/application.properties");
if (appProperties.exists()) {
try (InputStream stream = new FileInputStream(appProperties)) {
application.load(stream);
templateFile = apply(application, templateFile, SAM_TEMPLATE, DEFAULT_TEMPLATE);
resourceName = apply(application, resourceName, SAM_RESOURCE, DEFAULT_RESOURCE);
}
}
File configFile = new File(templateFile);
System.out.println("********************* configFile = " + configFile.getAbsolutePath());
Map template;
Map<String, Object> resource;
if (!configFile.exists()) {
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("template.yaml")) {
template = mapper.readValue(inputStream, LinkedHashMap.class);
Map<String, Object> resources = get(template, "Resources");
resource = get(resources, "Quarkus");
resources.remove("Quarkus");
resources.put(resourceName, resource);
}
} else {
try (InputStream inputStream = new FileInputStream(configFile)) {
template = mapper.readValue(inputStream, LinkedHashMap.class);
Map<String, Object> resources = get(template, "Resources");
resource = get(resources, resourceName);
if (resource == null && resources.size() == 1) {
resource = (Map<String, Object>) resources.entrySet().iterator().next().getValue();
}
}
}
if (resource != null) {
Map<String, Object> properties = get(resource, "Properties");
properties.put("Handler", SAM_HANDLER);
properties.put("Runtime", SAM_RUNTIME);
mapper.writer().withDefaultPrettyPrinter().writeValue(configFile, template);
} else {
throw new RuntimeException("Could not find the resource to update");
}
System.out.println("********************* template = " + template);
System.out.println("********************* new File(\".\").getAbsolutePath() = "
+ new File(".").getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private String apply(Properties properties, String field, String key, String defaultValue) {
String value = properties.getProperty(key);
if (value != null && field.equals(defaultValue)) {
field = value;
}
return field;
}
@SuppressWarnings("unchecked")
public static <T> T get(final Map template, final String... keys) {
Map map = template;
for (int i = 0; i < keys.length - 1; i++) {
map = (Map) map.get(keys[i]);
if (map == null) {
throw new IllegalArgumentException("No object found with the key: " + keys[i]);
}
}
return (T) map.get(keys[keys.length - 1]);
}
}

View File

@@ -0,0 +1,19 @@
---
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Globals:
Function:
Timeout: 5
Resources:
Quarkus:
Type: "AWS::Serverless::Function"
Properties:
Handler: io.quarkus.amazon.lambda.http.HttpHandler::handleRequest+somethingelse
Runtime: "java8"
Policies: "AWSLambdaBasicExecutionRole"
Events:
GetResource:
Type: "Api"
Properties:
Path: "/{proxy+}"
Method: "any"

View File

@@ -11,13 +11,14 @@
<relativePath>../../build-parent/pom.xml</relativePath>
</parent>
<artifactId>quarkus-amazon-sam-parent</artifactId>
<name>Quarkus - Amazon SAM</name>
<artifactId>quarkus-amazon-lambda-http-parent</artifactId>
<name>Quarkus - Amazon Lambda HTTP</name>
<packaging>pom</packaging>
<modules>
<module>runtime</module>
<module>deployment</module>
<module>maven</module>
</modules>
</project>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam-parent</artifactId>
<artifactId>quarkus-amazon-lambda-http-parent</artifactId>
<version>999-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>quarkus-amazon-sam</artifactId>
<name>Quarkus - Amazon SAM - Runtime</name>
<artifactId>quarkus-amazon-lambda-http</artifactId>
<name>Quarkus - Amazon Lambda HTTP - Runtime</name>
<dependencies>
<dependency>

View File

@@ -1,4 +1,21 @@
package io.quarkus.amazon.sam;
package io.quarkus.amazon.lambda.http;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.core.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler;
import com.amazonaws.serverless.proxy.internal.SecurityUtils;
@@ -12,6 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.DefaultLastHttpContent;
@@ -24,25 +42,10 @@ import io.netty.util.ReferenceCountUtil;
import io.quarkus.netty.runtime.virtual.VirtualClientConnection;
import io.quarkus.runtime.Application;
import io.quarkus.vertx.http.runtime.VertxHttpRecorder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.HttpHeaders;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("unused")
public class SamHandler implements RequestStreamHandler {
private static final Logger LOG = LoggerFactory.getLogger(SamHandler.class);
public class HttpHandler implements RequestStreamHandler {
private static final Logger LOG = LoggerFactory.getLogger(HttpHandler.class);
private static ObjectMapper objectMapper = new ObjectMapper();
private ObjectReader objectReader = objectMapper.readerFor(AwsProxyRequest.class);
@@ -137,7 +140,20 @@ public class SamHandler implements RequestStreamHandler {
}
}
if (msg instanceof LastHttpContent) {
response.setBody(new String(baos.toByteArray(), StandardCharsets.UTF_8));
String contentType = response.getMultiValueHeaders().getFirst("Content-Type");
//TODO: big hack, we should handle charset properly, base64 is always safe though
boolean requiresEncoding = true;
if (contentType != null) {
String ct = contentType.toLowerCase();
requiresEncoding = !ct.contains("charset=utf-8") && !ct.contains("json");
}
if (requiresEncoding) {
response.setBase64Encoded(true);
response.setBody(Base64.getMimeEncoder().encodeToString(baos.toByteArray()));
} else {
response.setBase64Encoded(false);
response.setBody(new String(baos.toByteArray(), StandardCharsets.UTF_8));
}
return response;
}
} finally {

View File

@@ -1,88 +0,0 @@
package io.quarkus.amazon.sam.deployment;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.quarkus.amazon.sam.AmazonSamConfig;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem;
public class AmazonSamProcessor {
public static final String SAM_HANDLER = "io.quarkus.amazon.lambda.resteasy.runtime.container.StreamLambdaHandler::handleRequest";
public static final String SAM_RUNTIME = "java8";
AmazonSamConfig config;
@BuildStep
public RequireVirtualHttpBuildItem requestVirtualHttp(LaunchModeBuildItem launchMode) {
return launchMode.getLaunchMode() == LaunchMode.NORMAL ? RequireVirtualHttpBuildItem.MARKER : null;
}
@SuppressWarnings("unchecked")
@BuildStep
void sam() {
if (config.updateConfig) {
try {
File configFile = new File(config.template);
if (!configFile.exists()) {
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("template.yaml")) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Map template = mapper.readValue(inputStream, LinkedHashMap.class);
Map<String, Object> resources = walk(template, "Resources");
Map<String, Object> resource = walk(resources, "QuarkusSam");
resources.put(config.resourceName, resource);
resources.remove("QuarkusSam");
mapper.writer().withDefaultPrettyPrinter().writeValue(configFile, template);
}
} else {
try (InputStream inputStream = new FileInputStream(configFile)) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Map template = mapper.readValue(inputStream, LinkedHashMap.class);
Map<String, Object> resources = walk(template, "Resources");
Map<String, Object> resource = walk(resources, config.resourceName);
if (resource == null && resources.size() == 1) {
resource = (Map<String, Object>) resources.entrySet().iterator().next().getValue();
}
if (resource != null) {
Map<String, Object> properties = walk(resource, "Properties");
properties.put("Handler", SAM_HANDLER);
properties.put("Runtime", SAM_RUNTIME);
}
mapper.writer().withDefaultPrettyPrinter().writeValue(configFile, template);
}
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
@SuppressWarnings("unchecked")
public static <T> T walk(final Map template, final String... keys) {
Map map = template;
for (int i = 0; i < keys.length - 1; i++) {
map = (Map) map.get(keys[i]);
if (map == null) {
throw new IllegalArgumentException("No object found with the key: " + keys[i]);
}
}
return (T) map.get(keys[keys.length - 1]);
}
}

View File

@@ -1,42 +0,0 @@
package io.quarkus.amazon.sam;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
@ConfigRoot(name = "amazon-sam", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class AmazonSamConfig {
/**
* The template file to create or update
*/
@ConfigItem(name = "sam-template", defaultValue = "template.yaml")
public String template;
/**
* Indicates if we are in debug mode.
*/
@ConfigItem(defaultValue = "false")
public boolean debug;
/**
* Indicates if we are in debug mode.
*/
@ConfigItem(defaultValue = "false")
public boolean updateConfig;
/**
* The name of the SAM resource
*/
@ConfigItem(name = "resource-name")
public String resourceName;
@Override
public String toString() {
return "AmazonSamConfig{" +
"debug=" + debug +
", resourceName='" + resourceName + '\'' +
", template='" + template + '\'' +
'}';
}
}

View File

@@ -105,7 +105,7 @@
<!-- Integrations -->
<module>amazon-lambda</module>
<module>amazon-sam</module>
<module>amazon-lambda-http</module>
<module>amazon-dynamodb</module>
<module>azure-functions-http</module>

View File

@@ -11,17 +11,19 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-integration-test-amazon-sam</artifactId>
<name>Quarkus - Integration Tests - Amazon Lambda HTTP</name>
<artifactId>quarkus-integration-test-amazon-lambda-http</artifactId>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
<artifactId>quarkus-amazon-lambda-http-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-sam-deployment</artifactId>
<artifactId>quarkus-amazon-lambda-http-maven</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
@@ -115,6 +117,7 @@
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>

View File

@@ -0,0 +1,130 @@
package io.quarkus.amazon.sam;
import static io.quarkus.amazon.lambda.http.AmazonLambdaHttpMojo.SAM_HANDLER;
import static io.quarkus.amazon.lambda.http.AmazonLambdaHttpMojo.SAM_RUNTIME;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.shared.invoker.MavenInvocationException;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.quarkus.amazon.lambda.http.AmazonLambdaHttpMojo;
import io.quarkus.maven.it.MojoTestBase;
import io.quarkus.maven.it.verifier.MavenProcessInvocationResult;
import io.quarkus.maven.it.verifier.RunningInvoker;
public class GenerateConfigIT extends MojoTestBase {
private File testDir;
private String template = "properties.yaml";
private String resource = "Quarkus";
// @Test
public void testConfigureWithNoTemplate() throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/configure-new-template");
template = "sam.yaml";
resource = "new-template";
invoke();
}
// @Test
public void testConfigureWithConfiguredName() throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/configure-named-template");
resource = "named-template";
invoke();
}
// @Test
public void testConfigureWithExistingTemplate() throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/configure-existing-template");
resource = "ThumbnailFunction";
invoke();
}
// @Test
@SuppressWarnings("unchecked")
public void testConfigureWithApplicationProperties() throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/configure-with-application-properties");
template = null;
resource = null;
invoke();
Map<String, Object> content = new ObjectMapper(new YAMLFactory())
.readValue(new File(testDir, "properties.yaml"), LinkedHashMap.class);
Map<String, Object> properties = AmazonLambdaHttpMojo.get(content, "Resources", "properties-resource", "Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
@Test
public void testConfigureDuringLifecycle() throws MavenInvocationException, IOException, InterruptedException {
testDir = initProject("projects/configure-during-lifecycle");
compile();
}
@SuppressWarnings("unchecked")
private void invoke() throws MavenInvocationException, IOException, InterruptedException {
Properties mavenProperties = new Properties();
mavenProperties.put("projectGroupId", "org.acme");
mavenProperties.put("projectArtifactId", "acme");
mavenProperties.put("projectVersion", "1.0-SNAPSHOT");
if (template != null)
mavenProperties.put("sam.template", template);
if (resource != null)
mavenProperties.put("sam.resource", resource);
RunningInvoker running = new RunningInvoker(testDir, false);
final MavenProcessInvocationResult result = running.execute(
singletonList("io.quarkus:quarkus-amazon-lambda-http-maven:configure-aws-lambda"), emptyMap(),
mavenProperties);
assertThat(result.getProcess().waitFor()).isEqualTo(0);
if (template != null && resource != null) {
Map<String, Object> content = new ObjectMapper(new YAMLFactory())
.readValue(new File(testDir, template), LinkedHashMap.class);
Map<String, Object> properties = AmazonLambdaHttpMojo.get(content, "Resources", resource, "Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
}
@SuppressWarnings("unchecked")
private void compile() throws MavenInvocationException, IOException, InterruptedException {
Properties mavenProperties = new Properties();
mavenProperties.put("projectGroupId", "org.acme");
mavenProperties.put("projectArtifactId", "acme");
mavenProperties.put("projectVersion", "1.0-SNAPSHOT");
RunningInvoker running = new RunningInvoker(testDir, false);
final MavenProcessInvocationResult result = running.execute(singletonList("compile"), emptyMap(),
mavenProperties);
assertThat(result.getProcess().waitFor()).isEqualTo(0);
Map<String, Object> content = new ObjectMapper(new YAMLFactory())
.readValue(new File(testDir, "properties.yaml"), LinkedHashMap.class);
System.out.println("********************* content = " + content);
Map<String, Object> properties = AmazonLambdaHttpMojo.get(content, "Resources", "properties-resource", "Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
}

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>existing-template</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<configuration>
<wiringClassesDirectory>target/classes/</wiringClassesDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-lambda-http-maven</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>configure-aws-lambda</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.version>999-SNAPSHOT</quarkus.version>
</properties>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-jsonb</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-jaxb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
Transform: 'AWS::Serverless-2016-10-31'
Resources:
properties-resource:
# This resource creates a Lambda function.
Type: 'AWS::Serverless::Function'
Properties:
# This function uses the Nodejs v6.10 runtime.
Runtime: nodejs6.10
# This is the Lambda function's handler.
Handler: index.handler
# The location of the Lambda function code.
CodeUri: ./src
# Event sources to attach to this function. In this case, we are attaching
# one API Gateway endpoint to the Lambda function. The function is
# called when a HTTP request is made to the API Gateway endpoint.
Events:
ThumbnailApi:
# Define an API Gateway endpoint that responds to HTTP GET at /thumbnail
Type: Api
Properties:
Path: /thumbnail
Method: GET

View File

@@ -0,0 +1,2 @@
quarkus.amazon-lambda-http.resource-name=properties-resource
quarkus.amazon-lambda-http.template=properties.yaml

View File

@@ -55,7 +55,7 @@
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>

View File

@@ -56,7 +56,7 @@
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>

View File

@@ -55,7 +55,7 @@
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-sam</artifactId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>

View File

@@ -0,0 +1,7 @@
package io.quarkus.amazon.sam.maven;
import javax.ws.rs.Path;
@Path("/sam")
public class SamApp {
}

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>existing-template</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<configuration>
<wiringClassesDirectory>target/classes/</wiringClassesDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.version>999-SNAPSHOT</quarkus.version>
</properties>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-jsonb</artifactId>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>quarkus-jaxb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
Transform: 'AWS::Serverless-2016-10-31'
Resources:
properties-resource:
# This resource creates a Lambda function.
Type: 'AWS::Serverless::Function'
Properties:
# This function uses the Nodejs v6.10 runtime.
Runtime: nodejs6.10
# This is the Lambda function's handler.
Handler: index.handler
# The location of the Lambda function code.
CodeUri: ./src
# Event sources to attach to this function. In this case, we are attaching
# one API Gateway endpoint to the Lambda function. The function is
# called when a HTTP request is made to the API Gateway endpoint.
Events:
ThumbnailApi:
# Define an API Gateway endpoint that responds to HTTP GET at /thumbnail
Type: Api
Properties:
Path: /thumbnail
Method: GET

View File

@@ -0,0 +1,7 @@
package io.quarkus.amazon.sam.maven;
import javax.ws.rs.Path;
@Path("/sam")
public class SamApp {
}

View File

@@ -0,0 +1,2 @@
quarkus.amazon-lambda-http.resource-name=properties-resource
quarkus.amazon-lambda-http.template=properties.yaml

View File

@@ -1,106 +0,0 @@
package io.quarkus.amazon.sam;
import static io.quarkus.amazon.sam.deployment.AmazonSamProcessor.SAM_HANDLER;
import static io.quarkus.amazon.sam.deployment.AmazonSamProcessor.SAM_RUNTIME;
import static io.quarkus.amazon.sam.deployment.AmazonSamProcessor.walk;
import static java.util.Arrays.asList;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvokerLogger;
import org.apache.maven.shared.invoker.MavenInvocationException;
import org.apache.maven.shared.invoker.PrintStreamLogger;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.quarkus.maven.it.MojoTestBase;
public class GenerateSamConfig extends MojoTestBase {
private File testDir;
private DefaultInvoker invoker;
@Test
public void testConfigureSAMWithNoTemplate() throws MavenInvocationException, IOException {
testDir = initProject("projects/configure-new-template");
initRepo();
Map<String, Object> properties = walk(invoke(testDir, "sam.yaml"), "Resources", "new-template", "Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
@Test
public void testConfigureSAMWithConfiguredName() throws MavenInvocationException, IOException {
testDir = initProject("projects/configure-named-template");
Map<String, Object> properties = walk(invoke(testDir, "sam.yaml"), "Resources", "named-template", "Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
@Test
public void testConfigureSAMWithExistingTemplate() throws MavenInvocationException, IOException {
testDir = initProject("projects/configure-existing-template");
initRepo();
Map<String, Object> properties = walk(invoke(testDir, "template.yaml"), "Resources", "ThumbnailFunction",
"Properties");
Assert.assertEquals(SAM_HANDLER, properties.get("Handler"));
Assert.assertEquals(SAM_RUNTIME, properties.get("Runtime"));
}
@SuppressWarnings("unchecked")
private Map<String, Object> loadFile(String template) throws IOException {
return new ObjectMapper(new YAMLFactory())
.readValue(new File(testDir, template), LinkedHashMap.class);
}
private void initRepo() {
invoker = new DefaultInvoker();
invoker.setWorkingDirectory(testDir);
String repo = System.getProperty("maven.repo");
if (repo == null) {
repo = new File(System.getProperty("user.home"), ".m2/repository").getAbsolutePath();
}
invoker.setLocalRepositoryDirectory(new File(repo));
}
private Map<String, Object> invoke(File testDir, String template) throws MavenInvocationException, IOException {
Properties properties = new Properties();
properties.put("projectGroupId", "org.acme");
properties.put("projectArtifactId", "acme");
properties.put("projectVersion", "1.0-SNAPSHOT");
return invoke(template, properties);
}
private Map<String, Object> invoke(String template, Properties properties) throws MavenInvocationException, IOException {
initRepo();
InvocationRequest request = new DefaultInvocationRequest();
request.setBatchMode(true);
request.setShowErrors(true);
request.setGoals(asList("package"));
request.setProperties(properties);
getEnv().forEach(request::addShellEnvironment);
File log = new File(testDir, "maven.log");
PrintStreamLogger logger = new PrintStreamLogger(new PrintStream(new FileOutputStream(log), false, "UTF-8"),
InvokerLogger.DEBUG);
invoker.setLogger(logger);
invoker.execute(request);
return loadFile(template);
}
}

View File

@@ -58,7 +58,7 @@
<module>amazon-dynamodb</module>
<module>test-extension</module>
<module>amazon-lambda</module>
<module>amazon-sam</module>
<module>amazon-lambda-http</module>
<module>kogito</module>
<module>kogito-maven</module>
<module>kubernetes-client</module>

View File

@@ -3,6 +3,7 @@ package io.quarkus.maven.it.verifier;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
@@ -60,12 +61,19 @@ public class RunningInvoker extends MavenProcessInvoker {
public MavenProcessInvocationResult execute(List<String> goals, Map<String, String> envVars)
throws MavenInvocationException {
return execute(goals, envVars, new Properties());
}
public MavenProcessInvocationResult execute(List<String> goals, Map<String, String> envVars, Properties properties)
throws MavenInvocationException {
DefaultInvocationRequest request = new DefaultInvocationRequest();
request.setGoals(goals);
request.setDebug(debug);
request.setLocalRepositoryDirectory(getLocalRepositoryDirectory());
request.setBaseDirectory(getWorkingDirectory());
request.setPomFile(new File(getWorkingDirectory(), "pom.xml"));
request.setProperties(properties);
if (System.getProperty("mavenOpts") != null) {
request.setMavenOpts(System.getProperty("mavenOpts"));