First iteration of support for Java

This commit is contained in:
Mukhtar Haji
2017-06-01 02:19:37 -07:00
committed by Matthew Gilliard
parent 82d612a754
commit cd0b68dfb7
12 changed files with 246 additions and 21 deletions

View File

@@ -1,5 +1,15 @@
package langs
import (
"errors"
"os"
"fmt"
)
var (
ErrBoilerplateExists = errors.New("Function boilerplate already exists")
)
// GetLangHelper returns a LangHelper for the passed in language
func GetLangHelper(lang string) LangHelper {
switch lang {
@@ -19,6 +29,8 @@ func GetLangHelper(lang string) LangHelper {
return &DotNetLangHelper{}
case "lambda-nodejs4.3":
return &LambdaNodeHelper{}
case "java":
return &JavaLangHelper{}
}
return nil
}
@@ -31,6 +43,11 @@ type LangHelper interface {
HasPreBuild() bool
PreBuild() error
AfterBuild() error
// HasBoilerplate indicates whether a language has support for generating function boilerplate.
HasBoilerplate() bool
// GenerateBoilerplate generates basic function boilerplate. Returns ErrBoilerplateExists if the function file
// already exists.
GenerateBoilerplate() error
}
// BaseHelper is empty implementation of LangHelper for embedding in implementations.
@@ -38,3 +55,18 @@ type BaseHelper struct {
}
func (h *BaseHelper) Cmd() string { return "" }
func (h *BaseHelper) HasBoilerplate() bool { return false }
func (h *BaseHelper) GenerateBoilerplate() error { return nil }
func exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
func dockerBuildError(err error) error {
return fmt.Errorf("error running docker build: %v", err)
}

View File

@@ -1,7 +1,6 @@
package langs
import (
"fmt"
"os"
"os/exec"
)
@@ -34,7 +33,7 @@ func (lh *DotNetLangHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}

View File

@@ -36,7 +36,7 @@ func (lh *GoLangHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}

118
fn/langs/java.go Normal file
View File

@@ -0,0 +1,118 @@
package langs
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
)
// JavaLangHelper provides a set of helper methods for the build lifecycle of the Java runtime
type JavaLangHelper struct {
BaseHelper
}
const (
mainClass = "Func"
mainClassFile = mainClass + ".java"
)
// Entrypoint returns the Java runtime Docker entrypoint that will be executed when the function is run
func (lh *JavaLangHelper) Entrypoint() string {
return fmt.Sprintf("java %s", mainClass)
}
// HasPreBuild returns whether the Java runtime has a pre-build step
func (lh *JavaLangHelper) HasPreBuild() bool {
return true
}
// PreBuild executes the pre-build step for the Java runtime which involves compiling the relevant classes. It expects
// the entrypoint to the function, in other words or the class with the main method (not to be confused with the Docker
// entrypoint from Entrypoint()) to be Function.java
func (lh *JavaLangHelper) PreBuild() error {
wd, err := os.Getwd()
if err != nil {
return err
}
if !exists(filepath.Join(wd, mainClassFile)) {
return fmt.Errorf("could not find function: for Java, class with main method must be "+
"called %s", mainClassFile)
}
cmd := exec.Command(
"docker", "run",
"--rm", "-v", wd+":/java", "-w", "/java",
"funcy/java:dev",
"/bin/sh", "-c", "javac "+mainClassFile,
)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return dockerBuildError(err)
}
return nil
}
// AfterBuild removes all compiled class files from the host machine
func (lh *JavaLangHelper) AfterBuild() error {
wd, err := os.Getwd()
if err != nil {
return err
}
files, err := filepath.Glob(filepath.Join(wd, "*.class"))
if err != nil {
return err
}
for _, file := range files {
err = os.Remove(file)
if err != nil {
return err
}
}
return nil
}
// HasPreBuild returns whether the Java runtime has boilerplate that can be generated.
func (lh *JavaLangHelper) HasBoilerplate() bool { return true }
const javaFunctionBoilerplate = `import java.io.*;
public class Func {
/**
* This is the entrypoint to your function. Input will be via STDIN.
* Any output sent to STDOUT will be sent back as the function result.
*/
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String name = bufferedReader.readLine();
name = (name == null) ? "world" : name;
System.out.println("Hello, " + name + "!");
}
}
`
// GenerateBoilerplate will generate function boilerplate (Function.java) for java if it does not exist.
// Returns ErrBoilerplateExists if the function file already exists
func (lh *JavaLangHelper) GenerateBoilerplate() error {
wd, err := os.Getwd()
if err != nil {
return err
}
pathToFunctionFile := filepath.Join(wd, mainClassFile)
if exists(filepath.Join(wd, mainClassFile)) {
return ErrBoilerplateExists
}
return ioutil.WriteFile(pathToFunctionFile, []byte(javaFunctionBoilerplate), os.FileMode(0644))
}

View File

@@ -39,7 +39,7 @@ func (lh *PhpLangHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}

View File

@@ -35,7 +35,7 @@ func (lh *PythonHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}

View File

@@ -39,20 +39,11 @@ func (lh *RubyLangHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}
func (lh *RubyLangHelper) AfterBuild() error {
return nil
}
func exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
}

View File

@@ -1,7 +1,6 @@
package langs
import (
"fmt"
"os"
"os/exec"
)
@@ -34,7 +33,7 @@ func (lh *RustLangHelper) PreBuild() error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
return dockerBuildError(err)
}
return nil
}