Example app structure. round 1.

This commit is contained in:
Travis Reeder
2017-09-14 16:09:28 -07:00
parent fdc3e76359
commit 75e2051169
25 changed files with 194 additions and 3 deletions

View File

@@ -79,7 +79,8 @@ func FromRequest(appName, path string, req *http.Request) CallOpt {
baseVars["FN_FORMAT"] = route.Format
baseVars["FN_APP_NAME"] = appName
baseVars["FN_ROUTE"] = route.Path
baseVars["FN_PATH"] = route.Path
// TODO: might be a good idea to pass in: envVars["FN_BASE_PATH"] = fmt.Sprintf("/r/%s", appName) || "/" if using DNS entries per app
baseVars["FN_MEMORY"] = fmt.Sprintf("%d", route.Memory)
baseVars["FN_TYPE"] = route.Type

View File

@@ -154,7 +154,7 @@ var (
}
)
// any error that implements this interface will return an API response
// APIError any error that implements this interface will return an API response
// with the provided status code and error message body
type APIError interface {
Code() int
@@ -170,7 +170,7 @@ func (e err) Code() int { return e.code }
func NewAPIError(code int, e error) APIError { return err{code, e} }
// uniform error output
// Error uniform error output
type Error struct {
Error *ErrorBody `json:"error,omitempty"`
}

7
examples/app/README.md Normal file
View File

@@ -0,0 +1,7 @@
# App Example
This shows you how to organize functions into a full application and deploy them easily with one command.
## TODOs
* [ ] Use a header/footer endpoint and pull them into the functions?

View File

@@ -0,0 +1,7 @@
puts %{
<div style="margin-top: 20px; border-top: 1px solid gray;">
<div><a href="/r/helloapp/ruby">Ruby</a></div><div><a href="/r/helloapp/node">Node</a></div><div><a href="/r/helloapp/python">Python</a></div>
</div>
</body>
</html>
}

View File

@@ -0,0 +1,7 @@
name: footer
version: 0.0.10
runtime: ruby
entrypoint: ruby func.rb
headers:
content-type:
- text/html

58
examples/app/func.go Normal file
View File

@@ -0,0 +1,58 @@
package main
import (
"fmt"
"html/template"
"log"
"os"
)
type Link struct {
Text string
Href string
}
func main() {
const tpl = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{.Title}}</title>
</head>
<body>
<h1>{{.Title}}</h1>
<p>{{.Body}}</p>
<div>
{{range .Items}}<div><a href="{{.Href}}">{{ .Text }}</a></div>{{else}}<div><strong>no rows</strong></div>{{end}}
</div>
</body>
</html>`
check := func(err error) {
if err != nil {
log.Fatal(err)
}
}
t, err := template.New("webpage").Parse(tpl)
check(err)
appName := os.Getenv("FN_APP_NAME")
data := struct {
Title string
Body string
Items []Link
}{
Title: "My App",
Body: "This is my app. It may not be the best app, but it's my app. And it's multilingual!",
Items: []Link{
Link{"Ruby", fmt.Sprintf("/r/%s/ruby", appName)},
Link{"Node", fmt.Sprintf("/r/%s/node", appName)},
Link{"Python", fmt.Sprintf("/r/%s/python", appName)},
},
}
err = t.Execute(os.Stdout, data)
check(err)
}

4
examples/app/func.yaml Normal file
View File

@@ -0,0 +1,4 @@
name: app
version: 0.0.68
runtime: go
entrypoint: ./func

View File

@@ -0,0 +1,9 @@
puts %{
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My App</title>
</head>
<body>
}

View File

@@ -0,0 +1,7 @@
name: header
version: 0.0.9
runtime: ruby
entrypoint: ruby func.rb
headers:
content-type:
- text/html

2
examples/app/node/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules/
Dockerfile

View File

@@ -0,0 +1 @@
# Node function

10
examples/app/node/func.js Normal file
View File

@@ -0,0 +1,10 @@
fs = require('fs');
name = "do you speak node?";
try {
obj = JSON.parse(fs.readFileSync('/dev/stdin').toString())
if (obj.name != "") {
name = obj.name
}
} catch(e) {}
console.log("Hello, " + name);

View File

@@ -0,0 +1,4 @@
name: node
version: 0.0.11
runtime: node
entrypoint: node func.js

View File

@@ -0,0 +1,7 @@
{
"name": "my-awesome-func",
"version": "1.0.0",
"dependencies": {
"is-positive": "^3.1.0"
}
}

1
examples/app/python/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
packages/

View File

@@ -0,0 +1 @@
# Python function

View File

@@ -0,0 +1,21 @@
import sys
import os
import json
sys.stderr.write("Starting Python Function\n")
name = "I speak Python too"
try:
if not os.isatty(sys.stdin.fileno()):
try:
obj = json.loads(sys.stdin.read())
if obj["name"] != "":
name = obj["name"]
except ValueError:
# ignore it
sys.stderr.write("no input, but that's ok\n")
except:
pass
print "Hello, " + name + "!"

View File

@@ -0,0 +1,4 @@
name: python
version: 0.0.9
runtime: python
entrypoint: python2 func.py

3
examples/app/ruby/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
bundle/
.bundle/
Dockerfile

View File

@@ -0,0 +1,3 @@
source 'https://rubygems.org'
gem 'json', '> 1.8.2'

View File

@@ -0,0 +1 @@
# Ruby function

25
examples/app/ruby/func.rb Normal file
View File

@@ -0,0 +1,25 @@
require 'uri'
require 'net/http'
require 'json'
name = "I love rubies"
payload = STDIN.read
if payload != ""
payload = JSON.parse(payload)
name = payload['name']
end
def open(url)
Net::HTTP.get(URI.parse(url))
end
h = "docker.for.mac.localhost" # ENV['HOSTNAME']
header = open("http://#{h}:8080/r/#{ENV['FN_APP_NAME']}/header") # todo: grab env vars to construct this
puts header
puts "Hello, #{name}! YOOO"
footer = open("http://#{h}:8080/r/#{ENV['FN_APP_NAME']}/footer") # todo: grab env vars to construct this
puts footer

View File

@@ -0,0 +1,7 @@
name: ruby
version: 0.0.21
runtime: ruby
entrypoint: ruby func.rb
headers:
content-type:
- text/html

View File

@@ -18,6 +18,7 @@ func main() {
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
// TODO: move these lines to a test, this was for testing log output issues
log.Println("---> stderr goes to the server logs.")
log.Println("---> LINE 2")
log.Println("---> LINE 3 with a break right here\nand LINE 4")