jvm-jersey-env (#1677)

A new Jersey framework based JVM environment which is lightweight and simpler.
This commit is contained in:
Sahil Lakhwani
2020-09-08 21:24:25 +05:30
committed by GitHub
parent 975286c2ac
commit 54b384efec
28 changed files with 1049 additions and 25 deletions
+2
View File
@@ -0,0 +1,2 @@
target/
bin/
+15
View File
@@ -0,0 +1,15 @@
FROM maven:3.5-jdk-8 as BUILD
WORKDIR /usr/src/myapp/
# To reuse the build cache, here we split maven dependency
# download and package into two RUN commands to avoid cache invalidation.
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src /usr/src/myapp/src/
RUN mvn package
FROM openjdk:8-jre-alpine
COPY --from=BUILD /usr/src/myapp/target/env-jvm-jersey-0.0.1.jar /app.jar
ENTRYPOINT java ${JVM_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar 8888
EXPOSE 8888
+15
View File
@@ -0,0 +1,15 @@
FROM maven:3.6-jdk-11 as BUILD
WORKDIR /usr/src/myapp/
# To reuse the build cache, here we split maven dependency
# download and package into two RUN commands to avoid cache invalidation.
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src /usr/src/myapp/src/
RUN mvn package
FROM openjdk:11-jre
COPY --from=BUILD /usr/src/myapp/target/env-jvm-jersey-0.0.1.jar /app.jar
ENTRYPOINT java ${JVM_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --server.port=8888
EXPOSE 8888
+68
View File
@@ -0,0 +1,68 @@
# Fission: Java and JVM-Jersey Environment
This is the JVM (Jersey based) environment for Fission.
It's a Docker image containing a OpenJDK8 runtime, along with a
dynamic loader. A few dependencies are included in the
pom.xml file.
Unlike the other [JVM environment](../jvm) which is based on the Spring framework, this environment uses Jersey.
Looking for ready-to-run examples? See the [JVM examples directory](../../examples/jvm-jersey).
## Customizing this image
To add package dependencies, edit pom.xml to add what you
need, and rebuild this image (instructions below).
## Rebuilding and pushing the image
You'll need access to a Docker registry to push the image: you can
sign up for Docker hub at hub.docker.com, or use registries from
gcr.io, quay.io, etc. Let's assume you're using a docker hub account
called USER. Build and push the image to the the registry:
```
docker build -t USER/jvm-jersey-env . && docker push USER/jvm-jersey-env
```
You can also create environment image based on JVM 11 using Dockerfile-11 in this directory.
## Using the image in fission
You can add this customized image to fission with "fission env
create":
```
fission env create --name jvm --image USER/jvm-jersey-env
```
Or, if you already have an environment, you can update its image:
```
fission env update --name jvm --image USER/jvm-jersey-env
```
After this, fission functions that have the env parameter set to the
same environment name as this command will use this environment.
## Web Server Framework
JVM Jersey environment uses an embedded Jetty HTTP server by default, as can be seen in the pom.xml file.
```
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.0.4.v20130625</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.0.4.v20130625</version>
</dependency>
```
## Java and JVM builder
There are two JVM environment builder based on OpenJDK8 and OpenJDK 11 and using Maven 3.5.4. The default build command runs `mvn clean package` and uses the target/*with-dependencies.jar file for function. The default build command can be overridden as long as the uber jar file is copied to ${DEPLOY_PKG}.
@@ -0,0 +1,48 @@
## Fission builder base image
ARG BUILDER_IMAGE=fission/builder:latest
FROM ${BUILDER_IMAGE}
## Section copied from the openjdk:8-jdk-alpine Dockerfile - (https://github.com/docker-library/openjdk/blob/47a6539cd18023dafb45db9013455136cc0bca07/8/jdk/alpine/Dockerfile)
ENV LANG C.UTF-8
RUN { \
echo '#!/bin/sh'; \
echo 'set -e'; \
echo; \
echo 'dirname "$(dirname "$(readlink -f "$(which javac || which java)")")"'; \
} > /usr/local/bin/docker-java-home \
&& chmod +x /usr/local/bin/docker-java-home
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
ENV PATH $PATH:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
ENV JAVA_VERSION 8u181
## Use "fuzzy" version matching to pin the version to a major/minor release
ENV JAVA_ALPINE_VERSION "~8"
RUN set -x \
&& apk add --no-cache \
openjdk8="$JAVA_ALPINE_VERSION" \
&& [ "$JAVA_HOME" = "$(docker-java-home)" ]
## Section copied from the Maven Dockerfile
RUN apk add --no-cache curl tar bash procps
ARG MAVEN_VERSION=3.5.4
ARG USER_HOME_DIR="/root"
ARG SHA=ce50b1c91364cb77efe3776f756a6d92b76d9038b0a0782f7d53acf1e997a14d
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries
RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
&& curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
&& echo "${SHA} /tmp/apache-maven.tar.gz" | sha256sum -c - \
&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
&& rm -f /tmp/apache-maven.tar.gz \
&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"
## Fission builder specific section
ADD build.sh /usr/local/bin/build
EXPOSE 8001
@@ -0,0 +1,43 @@
## Fission builder base image
ARG BUILDER_IMAGE=fission/builder:latest
FROM ${BUILDER_IMAGE}
## Section referred from the openjdk:8-jdk-alpine Dockerfile - (https://github.com/docker-library/openjdk/blob/47a6539cd18023dafb45db9013455136cc0bca07/8/jdk/alpine/Dockerfile)
ENV LANG C.UTF-8
RUN { \
echo '#!/bin/sh'; \
echo 'set -e'; \
echo; \
echo 'dirname "$(dirname "$(readlink -f "$(which javac || which java)")")"'; \
} > /usr/local/bin/docker-java-home \
&& chmod +x /usr/local/bin/docker-java-home
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk
ENV PATH $PATH:/usr/lib/jvm/java-11-openjdk/jre/bin:/usr/lib/jvm/java-11-openjdk/bin
RUN set -x \
&& apk add --no-cache openjdk11 \
&& [ "$JAVA_HOME" = "$(docker-java-home)" ]
## Section copied from the Maven Dockerfile
RUN apk add --no-cache curl tar bash procps
ARG MAVEN_VERSION=3.5.4
ARG USER_HOME_DIR="/root"
ARG SHA=ce50b1c91364cb77efe3776f756a6d92b76d9038b0a0782f7d53acf1e997a14d
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries
RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
&& curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
&& echo "${SHA} /tmp/apache-maven.tar.gz" | sha256sum -c - \
&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
&& rm -f /tmp/apache-maven.tar.gz \
&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"
## Fission builder specific section
ADD build.sh /usr/local/bin/build
EXPOSE 8001
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
set -eou pipefail
mvn clean package
cp ${SRC_PKG}/target/*with-dependencies.jar ${DEPLOY_PKG}
+86
View File
@@ -0,0 +1,86 @@
<?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>
<groupId>io.fission</groupId>
<artifactId>env-jvm-jersey</artifactId>
<version>0.0.1</version>
<properties>
<java.source.level>1.6</java.source.level>
<java.target.level>1.6</java.target.level>
</properties>
<dependencies>
<dependency>
<groupId>io.fission</groupId>
<artifactId>fission-jvm-jersey</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.0.4.v20130625</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.0.4.v20130625</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.source.level}</source>
<target>${java.target.level}</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>io.fission.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,35 @@
package io.fission;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class FunctionLoadRequest {
private String filepath;
private String functionName;
private String url;
String getFilepath() {
return filepath;
}
void setFilepath(String filepath) {
this.filepath = filepath;
}
String getUrl() {
return url;
}
void setUrl(String url) {
this.url = url;
}
public String getFunctionName() {
return functionName;
}
public void setFunctionName(String functionName) {
this.functionName = functionName;
}
}
@@ -0,0 +1,147 @@
package io.fission;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Context;
import javax.ws.rs.container.ContainerRequestContext;
import io.fission.Function;
@Path("/")
public class JerseyServer {
private static Function<ContainerRequestContext,Response> fn;
private static final int CLASS_LENGTH = 6;
private static Logger logger = Logger.getGlobal();
@GET
public Response home(@Context ContainerRequestContext request) {
return callUserFunction(request);
}
@POST
public Response homePost(@Context ContainerRequestContext request) {
return callUserFunction(request);
}
@PUT
public Response homePut(@Context ContainerRequestContext request) {
return callUserFunction(request);
}
@DELETE
public Response homeDelete(@Context ContainerRequestContext request) {
return callUserFunction(request);
}
@Path("v2/specialize")
@POST
public Response specialize(FunctionLoadRequest req) {
long startTime = System.nanoTime();
File file = new File(req.getFilepath());
if (!file.exists()) {
return Response.status(Response.Status.BAD_REQUEST).entity("/userfunc/usernot found").build();
}
String entryPoint = req.getFunctionName();
logger.log(Level.INFO, "Entrypoint class:" + entryPoint);
if (entryPoint == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Entrypoint class is missing in the JAR or the name is incorrect")
.build();
}
JarFile jarFile = null;
ClassLoader cl = null;
try {
jarFile = new JarFile(file);
Enumeration<JarEntry> e = jarFile.entries();
URL[] urls = { new URL("jar:file:" + file + "!/") };
// TODO Check if the classloading can be improved for ex. use something like:
// Thread.currentThread().setContextClassLoader(cl);
if (this.getClass().getClassLoader() == null) {
cl = URLClassLoader.newInstance(urls);
} else {
cl = URLClassLoader.newInstance(urls, this.getClass().getClassLoader());
}
if (cl == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Failed to initialize the classloader")
.build();
}
// Load all dependent classes from libraries etc.
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
String className = je.getName().substring(0, je.getName().length() - CLASS_LENGTH);
className = className.replace('/', '.');
cl.loadClass(className);
}
// Instantiate the function class
fn = (Function) cl.loadClass(entryPoint).newInstance();
} catch (MalformedURLException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST).entity("Entrypoint class is missing in the function")
.build();
} catch (ClassNotFoundException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST).entity("Error loading Function or dependent class")
.build();
} catch (InstantiationException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST)
.entity("Error creating a new instance of function class").build();
} catch (IllegalAccessException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST)
.entity("Error creating a new instance of function class").build();
} catch (IOException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST).entity("Error reading the JAR file").build();
} finally {
try {
jarFile.close();
} catch (IOException e) {
e.printStackTrace();
return Response.status(Response.Status.BAD_REQUEST)
.entity("Error closing the file while loading the class").build();
}
}
long elapsedTime = System.nanoTime() - startTime;
logger.log(Level.INFO, "Specialize call done in: " + elapsedTime / 1000000 + " ms");
return Response.status(Response.Status.OK).entity("Done").build();
}
private Response callUserFunction(ContainerRequestContext httpRequest) {
if (fn == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Container not specialized").build();
} else {
return fn.call(httpRequest, null);
}
}
}
@@ -0,0 +1,50 @@
package io.fission;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
private static final int DEFAULT_PORT = 8888;
private int serverPort;
public Main(int serverPort) throws Exception {
this.serverPort = serverPort;
Server server = configureServer();
server.start();
server.join();
}
private Server configureServer() {
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.packages(JerseyServer.class.getPackage().getName());
resourceConfig.register(JacksonFeature.class);
ServletContainer servletContainer = new ServletContainer(resourceConfig);
ServletHolder sh = new ServletHolder(servletContainer);
Server server = new Server(serverPort);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(sh, "/*");
server.setHandler(context);
return server;
}
public static void main(String[] args) throws Exception {
int serverPort = DEFAULT_PORT;
if(args.length >= 1) {
try {
serverPort = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
new Main(serverPort);
}
}
+4
View File
@@ -0,0 +1,4 @@
.project
.settings
.classpath
target/
+60
View File
@@ -0,0 +1,60 @@
# Hello World in JVM/Java on Fission
The `io.fission.HelloWorld.java` class is a very simple fission function that implements `io.fission.Function` and says "Hello, World!" .
## Building and deploying using Fission
Fission's builder can be used to create the binary artifact from source code. Create an environment with builder image and then create a package.
```
$ zip -r java-src-pkg.zip *
$ fission env create --name java --image fission/jvm-env --version 2 --keeparchive --builder fission/jvm-builder
$ fission package create --sourcearchive java-src-pkg.zip --env java
java-src-pkg-zip-tvd0
$ fission package info --name java-src-pkg-zip-tvd0
Name: java-src-pkg-zip-tvd0
Environment: java
Status: succeeded
Build Logs:
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< io.fission:hello-world >-----------------------
[INFO] Building hello-world 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
```
Once package's status is `succeeded` then that package can be used to create and execute a function.
```
$ fission fn create --name hello --pkg java-src-pkg-zip-tvd0 --env java --entrypoint io.fission.HelloWorld
$ fission fn test --name hello
Hello World!
```
## Building locally and deploying with Fission
You can build the jar file in one of the two ways below based on your setup:
- You can use docker without the need to install JDK and Maven to build the jar file from source code:
```bash
$ bash -x ./build.sh
```
- If you have JDK and Maven installed, you can directly build the JAR file using command:
```
$ mvn clean package
```
Both of above steps will generate a target subdirectory which has the archive `target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar` which will be used for creating function.
- The archive created above will be used as a deploy package when creating the function.
```
$ fission env create --name jvm --image fission/jvm-env --version 2 --keeparchive=true
$ fission fn create --name hello --deploy target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar --env jvm --entrypoint io.fission.HelloWorld
$ fission route create --function hello --url /hellop --method GET
$ fission fn test --name hello
Hello World!
```
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
# This script allows you to build the jar without needing Maven & JDK installed locally.
# You need docker, as it uses a Docker image to build source code
set -eou pipefail
docker run -it --rm -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.5-jdk-8 mvn clean package
+76
View File
@@ -0,0 +1,76 @@
<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>
<groupId>io.fission</groupId>
<artifactId>jersey-hello-world</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>hello-world</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.fission</groupId>
<artifactId>fission-jvm-jersey</artifactId>
<version>0.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
</project>
+42
View File
@@ -0,0 +1,42 @@
Fission Specs
=============
This is a set of specifications for a Fission app. This includes functions,
environments, and triggers; we collectively call these things "resources".
How to use these specs
----------------------
These specs are handled with the 'fission spec' command. See 'fission spec --help'.
'fission spec apply' will "apply" all resources specified in this directory to your
cluster. That means it checks what resources exist on your cluster, what resources are
specified in the specs directory, and reconciles the difference by creating, updating or
deleting resources on the cluster.
'fission spec apply' will also package up your source code (or compiled binaries) and
upload the archives to the cluster if needed. It uses 'ArchiveUploadSpec' resources in
this directory to figure out which files to archive.
You can use 'fission spec apply --watch' to watch for file changes and continuously keep
the cluster updated.
You can add YAMLs to this directory by writing them manually, but it's easier to generate
them. Use 'fission function create --spec' to generate a function spec,
'fission environment create --spec' to generate an environment spec, and so on.
You can edit any of the files in this directory, except 'fission-deployment-config.yaml',
which contains a UID that you should never change. To apply your changes simply use
'fission spec apply'.
fission-deployment-config.yaml
------------------------------
fission-deployment-config.yaml contains a UID. This UID is what fission uses to correlate
resources on the cluster to resources in this directory.
All resources created by 'fission spec apply' are annotated with this UID. Resources on
the cluster that are _not_ annotated with this UID are never modified or deleted by
fission.
@@ -0,0 +1,17 @@
apiVersion: fission.io/v1
kind: Environment
metadata:
creationTimestamp: null
name: java-jersey
namespace: default
spec:
builder:
command: build
image: fission/jvm-jersey-builder
imagepullsecret: ""
keeparchive: true
poolsize: 3
resources: {}
runtime:
image: fission/jvm-jersey-env
version: 2
@@ -0,0 +1,7 @@
# This file is generated by the 'fission spec init' command.
# See the README in this directory for background and usage information.
# Do not edit the UID below: that will break 'fission spec apply'
apiVersion: fission.io/v1
kind: DeploymentConfig
name: java-jersey
uid: 908a303a-bf23-4bae-a22c-b1db9a1f71a9
@@ -0,0 +1,27 @@
apiVersion: fission.io/v1
kind: Function
metadata:
creationTimestamp: null
name: hello
namespace: default
spec:
InvokeStrategy:
ExecutionStrategy:
ExecutorType: poolmgr
MaxScale: 0
MinScale: 0
SpecializationTimeout: 120
TargetCPUPercent: 0
StrategyType: execution
configmaps: null
environment:
name: java-jersey
namespace: default
functionTimeout: 60
package:
functionName: io.fission.HelloWorld
packageref:
name: hellojava
namespace: default
resources: {}
secrets: null
@@ -0,0 +1,26 @@
include:
- src
- pom.xml
kind: ArchiveUploadSpec
name: src-URlE
---
apiVersion: fission.io/v1
kind: Package
metadata:
creationTimestamp: null
name: hellojavajersey
namespace: default
spec:
deployment:
checksum: {}
environment:
name: java-jersey
namespace: default
source:
checksum: {}
type: url
url: archive://src-URlE
status:
buildstatus: pending
lastUpdateTimestamp: "2020-01-29T09:43:56Z"
@@ -0,0 +1,25 @@
package io.fission;
import javax.ws.rs.core.Response;
import javax.ws.rs.container.ContainerRequestContext;
import io.fission.Function;
import java.io.BufferedReader;
import java.util.stream.Collectors;
import java.io.InputStreamReader;
public class HelloWorld implements Function<ContainerRequestContext,Response> {
public static final String RETURN_STRING = "Hello World!";
@Override
public Response call(ContainerRequestContext request, Context arg1) {
if(request.getMethod().equals("GET")) {
return Response.ok(RETURN_STRING).build();
}
else {
String body = new BufferedReader(new InputStreamReader(request.getEntityStream())).lines()
.parallel().collect(Collectors.joining("\n"));
return Response.ok("Echo: " + body).build();
}
}
}
@@ -0,0 +1,25 @@
package io.fission;
import java.net.URI;
import java.net.URISyntaxException;
import org.glassfish.jersey.server.ContainerRequest;
import javax.ws.rs.core.Response;
import org.junit.Assert;
import org.junit.Test;
public class HelloWorldTest {
@Test
public void testResponse() {
HelloWorld hw = new HelloWorld();
ContainerRequest request = null;
try {
request = new ContainerRequest(new URI("http://example.com/"),new URI("/hello"),"GET",null,null);
} catch (URISyntaxException e) {
e.printStackTrace();
}
Response response = hw.call(request, null);
Assert.assertTrue(response.getEntity().toString().equals(HelloWorld.RETURN_STRING));
}
}
+16 -13
View File
@@ -148,6 +148,8 @@ build_all_envs() {
build_env_image "$version" "python" "python-env" "2.7"
build_env_image "$version" "ruby" "ruby-env" ""
build_env_image "$version" "jvm" "jvm-env" ""
build_env_image "$version" "jvm-jersey" "jvm-jersey-env" ""
build_env_image "$version" "jvm-jersey" "jvm-jersey-env" "11"
build_env_image "$version" "tensorflow-serving" "tensorflow-serving-env" ""
}
@@ -180,19 +182,20 @@ build_all_env_builders() {
local version=$1
# call with version, env dir, image name base, image name variant
build_env_builder_image "$version" "python" "python-builder" ""
build_env_builder_image "$version" "binary" "binary-builder" ""
build_env_builder_image "$version" "go" "go-builder" ""
build_env_builder_image "$version" "go" "go-builder" "1.11.4"
build_env_builder_image "$version" "go" "go-builder" "1.12"
build_env_builder_image "$version" "go" "go-builder" "1.13"
build_env_builder_image "$version" "go" "go-builder" "1.14"
build_env_builder_image "$version" "jvm" "jvm-builder" ""
build_env_builder_image "$version" "nodejs" "node-builder" ""
build_env_builder_image "$version" "nodejs" "node-builder" "12.16"
build_env_builder_image "$version" "php7" "php-builder" ""
build_env_builder_image "$version" "ruby" "ruby-builder" ""
build_env_builder_image "$version" "dotnet20" "dotnet20-builder" ""
build_env_builder_image "$version" "python" "python-builder" ""
build_env_builder_image "$version" "binary" "binary-builder" ""
build_env_builder_image "$version" "go" "go-builder" ""
build_env_builder_image "$version" "go" "go-builder" "1.11.4"
build_env_builder_image "$version" "go" "go-builder" "1.12"
build_env_builder_image "$version" "go" "go-builder" "1.13"
build_env_builder_image "$version" "go" "go-builder" "1.14"
build_env_builder_image "$version" "jvm" "jvm-builder" ""
build_env_builder_image "$version" "jvm-jersey" "jvm-jersey-builder" ""
build_env_builder_image "$version" "jvm-jersey" "jvm-jersey-builder" "11"
build_env_builder_image "$version" "nodejs" "node-builder" ""
build_env_builder_image "$version" "php7" "php-builder" ""
build_env_builder_image "$version" "ruby" "ruby-builder" ""
build_env_builder_image "$version" "dotnet20" "dotnet20-builder" ""
}
build_charts() {
+16 -12
View File
@@ -89,6 +89,8 @@ push_all_envs() {
push_env_image "$version" "python" "python-env" "2.7"
push_env_image "$version" "ruby" "ruby-env" ""
push_env_image "$version" "jvm" "jvm-env" ""
push_env_image "$version" "jvm-jersey" "jvm-jersey-env" ""
push_env_image "$version" "jvm-jersey" "jvm-jersey-env" "11"
push_env_image "$version" "tensorflow-serving" "tensorflow-serving-env" ""
}
@@ -117,18 +119,20 @@ push_all_env_builders() {
local version=$1
# call with version, env dir, image name base, image name variant
push_env_builder_image "$version" "python" "python-builder" ""
push_env_builder_image "$version" "binary" "binary-builder" ""
push_env_builder_image "$version" "go" "go-builder" ""
push_env_builder_image "$version" "go" "go-builder" "1.11.4"
push_env_builder_image "$version" "go" "go-builder" "1.12"
push_env_builder_image "$version" "go" "go-builder" "1.13"
push_env_builder_image "$version" "go" "go-builder" "1.14"
push_env_builder_image "$version" "jvm" "jvm-builder" ""
push_env_builder_image "$version" "nodejs" "node-builder" ""
push_env_builder_image "$version" "ruby" "ruby-builder" ""
push_env_builder_image "$version" "dotnet20" "dotnet20-builder" ""
push_env_builder_image "$version" "php7" "php-builder" ""
push_env_builder_image "$version" "python" "python-builder" ""
push_env_builder_image "$version" "binary" "binary-builder" ""
push_env_builder_image "$version" "go" "go-builder" ""
push_env_builder_image "$version" "go" "go-builder" "1.11.4"
push_env_builder_image "$version" "go" "go-builder" "1.12"
push_env_builder_image "$version" "go" "go-builder" "1.13"
push_env_builder_image "$version" "go" "go-builder" "1.14"
push_env_builder_image "$version" "jvm" "jvm-builder" ""
push_env_builder_image "$version" "jvm-jersey" "jvm-jersey-builder" ""
push_env_builder_image "$version" "jvm-jersey" "jvm-jersey-builder" "11"
push_env_builder_image "$version" "nodejs" "node-builder" ""
push_env_builder_image "$version" "ruby" "ruby-builder" ""
push_env_builder_image "$version" "dotnet20" "dotnet20-builder" ""
push_env_builder_image "$version" "php7" "php-builder" ""
}
# Push pre-upgrade-checks image
+2
View File
@@ -29,12 +29,14 @@ build_and_push_builder $BUILDER_IMAGE:$TAG $REPO/go-mod-image-cache
build_and_push_env_runtime python $REPO/python-env:$TAG ""
build_and_push_env_runtime jvm $REPO/jvm-env:$TAG ""
build_and_push_env_runtime jvm-jersey $REPO/jvm-jersey-env:$TAG ""
build_and_push_env_runtime go $REPO/go-env:$TAG "1.12"
build_and_push_env_runtime nodejs $REPO/node-env:$TAG "12.16"
build_and_push_env_runtime tensorflow-serving $REPO/tensorflow-serving-env:$TAG ""
build_and_push_env_builder python $REPO/python-env-builder:$TAG $BUILDER_IMAGE:$TAG ""
build_and_push_env_builder jvm $REPO/jvm-env-builder:$TAG $BUILDER_IMAGE:$TAG ""
build_and_push_env_builder jvm-jersey $REPO/jvm-jersey-env-builder:$TAG $BUILDER_IMAGE:$TAG ""
build_and_push_env_builder go $REPO/go-env-builder:$TAG $BUILDER_IMAGE:$TAG "1.12"
build_and_push_env_builder nodejs $REPO/node-env-builder:$TAG $BUILDER_IMAGE:$TAG "12.16"
+1
View File
@@ -505,6 +505,7 @@ run_all_tests() {
export GO_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/go-env:${imageTag}
export GO_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/go-env-builder:${imageTag}
export JVM_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/jvm-env:${imageTag}
export JVM_JERSEY_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/jvm-jersey-env:${imageTag}
export JVM_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/jvm-env-builder:${imageTag}
export NODE_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/node-env:${imageTag}
export NODE_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/node-env-builder:${imageTag}
+186
View File
@@ -0,0 +1,186 @@
#!/bin/bash
set -euo pipefail
source $(dirname $0)/../../utils.sh
TEST_ID=$(generate_test_id)
echo "TEST_ID = $TEST_ID"
ROOT=$(dirname $0)/../../..
env=jvm-$TEST_ID
fn_n=jvm-hello-n-$TEST_ID
fn_p=jvm-hello-p-$TEST_ID
fn_n_p=jvm-hello-n-post-$TEST_ID
xmlBody=$(cat <<-END
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
<book id="bk103">
<author>Corets, Eva</author>
<title>Maeve Ascendant</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-11-17</publish_date>
<description>After the collapse of a nanotechnology
society in England, the young survivors lay the
foundation for a new society.</description>
</book>
<book id="bk104">
<author>Corets, Eva</author>
<title>Oberon's Legacy</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2001-03-10</publish_date>
<description>In post-apocalypse England, the mysterious
agent known only as Oberon helps to create a new life
for the inhabitants of London. Sequel to Maeve
Ascendant.</description>
</book>
<book id="bk105">
<author>Corets, Eva</author>
<title>The Sundered Grail</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2001-09-10</publish_date>
<description>The two daughters of Maeve, half-sisters,
battle one another for control of England. Sequel to
Oberon's Legacy.</description>
</book>
<book id="bk106">
<author>Randall, Cynthia</author>
<title>Lover Birds</title>
<genre>Romance</genre>
<price>4.95</price>
<publish_date>2000-09-02</publish_date>
<description>When Carla meets Paul at an ornithology
conference, tempers fly as feathers get ruffled.</description>
</book>
<book id="bk107">
<author>Thurman, Paula</author>
<title>Splish Splash</title>
<genre>Romance</genre>
<price>4.95</price>
<publish_date>2000-11-02</publish_date>
<description>A deep sea diver finds true love twenty
thousand leagues beneath the sea.</description>
</book>
<book id="bk108">
<author>Knorr, Stefan</author>
<title>Creepy Crawlies</title>
<genre>Horror</genre>
<price>4.95</price>
<publish_date>2000-12-06</publish_date>
<description>An anthology of horror stories about roaches,
centipedes, scorpions and other insects.</description>
</book>
<book id="bk109">
<author>Kress, Peter</author>
<title>Paradox Lost</title>
<genre>Science Fiction</genre>
<price>6.95</price>
<publish_date>2000-11-02</publish_date>
<description>After an inadvertant trip through a Heisenberg
Uncertainty Device, James Salway discovers the problems
of being quantum.</description>
</book>
<book id="bk110">
<author>O'Brien, Tim</author>
<title>Microsoft .NET: The Programming Bible</title>
<genre>Computer</genre>
<price>36.95</price>
<publish_date>2000-12-09</publish_date>
<description>Microsoft's .NET initiative is explored in
detail in this deep programmer's reference.</description>
</book>
<book id="bk111">
<author>O'Brien, Tim</author>
<title>MSXML3: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>36.95</price>
<publish_date>2000-12-01</publish_date>
<description>The Microsoft MSXML3 parser is covered in
detail, with attention to XML DOM interfaces, XSLT processing,
SAX and more.</description>
</book>
<book id="bk112">
<author>Galos, Mike</author>
<title>Visual Studio 7: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>49.95</price>
<publish_date>2001-04-16</publish_date>
<description>Microsoft Visual Studio 7 is explored in depth,
looking at how Visual Basic, Visual C++, C#, and ASP+ are
integrated into a comprehensive development
environment.</description>
</book>
</catalog>
END
)
cleanup() {
clean_resource_by_id $TEST_ID
}
if [ -z "${TEST_NOCLEANUP:-}" ]; then
trap cleanup EXIT
else
log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards."
fi
cd $ROOT/examples/jvm-jersey/java
log "Creating the jar from application"
#Using Docker to build Jar so that maven & other Java dependencies are not needed on CI server
docker run --rm -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.5-jdk-8 mvn clean package -q
log "Creating environment for Java"
fission env create --name $env --image $JVM_JERSEY_RUNTIME_IMAGE --version 2 --keeparchive=true
log "Creating pool manager & new deployment function for Java"
fission fn create --name $fn_p --deploy target/jersey-hello-world-0.0.1-jar-with-dependencies.jar --env $env --entrypoint io.fission.HelloWorld
fission fn create --name $fn_n --deploy target/jersey-hello-world-0.0.1-jar-with-dependencies.jar --env $env --executortype newdeploy --entrypoint io.fission.HelloWorld
log "Creating route for pool manager function"
fission route create --name $fn_p --function $fn_p --url /$fn_p --method GET
log "Creating route for new deployment function"
fission route create --name $fn_n --function $fn_n --url /$fn_n --method GET
log "Creating post route for new deployment function"
fission route create --name $fn_n_p --function $fn_n --url /$fn_n_p --method POST
log "Waiting for router & pools to catch up"
sleep 10
log "Testing pool manager function"
timeout 60 bash -c "test_fn $fn_p Hello"
log "Testing new deployment function"
timeout 60 bash -c "test_fn $fn_n Hello"
log "Testing new deployment function for XML POST request"
timeout 60 bash -c "test_post_route $fn_n_p \"$xmlBody\" \"Echo: $xmlBody\""
log "Test PASSED"
+1
View File
@@ -186,6 +186,7 @@ export PYTHON_BUILDER_IMAGE=${PYTHON_BUILDER_IMAGE:-fission/python-builder}
export GO_RUNTIME_IMAGE=${GO_RUNTIME_IMAGE:-fission/go-env-1.12}
export GO_BUILDER_IMAGE=${GO_BUILDER_IMAGE:-fission/go-builder-1.12}
export JVM_RUNTIME_IMAGE=${JVM_RUNTIME_IMAGE:-fission/jvm-env}
export JVM_JERSEY_RUNTIME_IMAGE=${JVM_JERSEY_RUNTIME_IMAGE:-fission/jvm-jersey-env}
export JVM_BUILDER_IMAGE=${JVM_BUILDER_IMAGE:-fission/jvm-builder}
export NODE_RUNTIME_IMAGE=${NODE_RUNTIME_IMAGE:-fission/node-env}
export NODE_BUILDER_IMAGE=${NODE_BUILDER_IMAGE:-fission/node-env-builder}