mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Postgres Example (#490)
* creating postgres example - fixes #489 * postgres example glide fix * all the changes * use fn call * removing func.yaml * removing build.sh * test.sh cleanup
This commit is contained in:
committed by
Travis Reeder
parent
67af2757cd
commit
d565cc6afe
4
examples/postgres/.gitignore
vendored
Normal file
4
examples/postgres/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/func
|
||||||
|
vendor
|
||||||
|
|
||||||
|
func.yaml
|
||||||
25
examples/postgres/README.md
Normal file
25
examples/postgres/README.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Postgres INSERT/SELECT Function Image
|
||||||
|
|
||||||
|
This function executes an INSERT or SELECT against a table in a given postgres server.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create your func.yaml file
|
||||||
|
fn init <YOUR_DOCKERHUB_USERNAME>/func-postgres
|
||||||
|
# Build the function
|
||||||
|
fn build
|
||||||
|
# Test it
|
||||||
|
./test.sh
|
||||||
|
# Push it to Docker Hub
|
||||||
|
fn push
|
||||||
|
# Create routes to this function on IronFunctions
|
||||||
|
fn apps create <YOUR_APP> --config SERVER=<POSTGRES>
|
||||||
|
fn routes create --config TABLE=<TABLE_NAME> --config COMMAND=INSERT <YOUR_APP> /<TABLE_NAME>/insert
|
||||||
|
fn routes create --config TABLE=<TABLE_NAME> --config COMMAND=SELECT <YOUR_APP> /<TABLE_NAME>/select
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can call your function on IronFunctions:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo <JSON_RECORD> | fn call /<YOUR_APP>/<TABLE_NAME>/insert
|
||||||
|
echo <JSON_QUERY> | fn call /<YOUR_APP>/<TABLE_NAME>/select
|
||||||
|
```
|
||||||
103
examples/postgres/func.go
Normal file
103
examples/postgres/func.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// command to execute, 'SELECT' or 'INSERT'
|
||||||
|
command = os.Getenv("HEADER_COMMAND")
|
||||||
|
// postgres host:port, e.g. 'postgres:5432'
|
||||||
|
server = os.Getenv("HEADER_SERVER")
|
||||||
|
// postgres table name
|
||||||
|
table = os.Getenv("HEADER_TABLE")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
req, err := ioutil.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(errors.Wrap(err, "failed to read stdin"))
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := sql.Open("postgres", "postgres://postgres@" + server + "?sslmode=disable")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Failed to connect to postgres server")
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch command {
|
||||||
|
case "SELECT":
|
||||||
|
if resp, err := selectCommand(req, db); err != nil {
|
||||||
|
log.Fatal(errors.Wrap(err, "select command failed"))
|
||||||
|
} else {
|
||||||
|
log.Println(resp)
|
||||||
|
}
|
||||||
|
case "INSERT":
|
||||||
|
if err := insertCommand(req, db); err != nil {
|
||||||
|
log.Fatal(errors.Wrap(err, "insert command failed"))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatalf("invalid command: %q", command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectCommand(req []byte, db *sql.DB) (string, error) {
|
||||||
|
// Parse request JSON
|
||||||
|
var params map[string]interface{}
|
||||||
|
if err := json.Unmarshal(req, ¶ms); err != nil {
|
||||||
|
return "", errors.Wrap(err, "failed to parse json")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build query and gather arguments
|
||||||
|
var query bytes.Buffer
|
||||||
|
var args []interface{}
|
||||||
|
|
||||||
|
query.WriteString("SELECT json_agg(t) FROM (SELECT * FROM ")
|
||||||
|
query.WriteString(table)
|
||||||
|
query.WriteString(" WHERE")
|
||||||
|
first := true
|
||||||
|
arg := 1
|
||||||
|
for k, v := range params {
|
||||||
|
args = append(args, v)
|
||||||
|
|
||||||
|
if !first {
|
||||||
|
query.WriteString(" AND")
|
||||||
|
}
|
||||||
|
query.WriteString(" ")
|
||||||
|
query.WriteString(k)
|
||||||
|
query.WriteString("=$")
|
||||||
|
query.WriteString(strconv.Itoa(arg))
|
||||||
|
arg += 1
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
query.WriteString(") AS t")
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
r := db.QueryRow(query.String(), args...)
|
||||||
|
var resp string
|
||||||
|
if err := r.Scan(&resp); err != nil {
|
||||||
|
return "", errors.Wrap(err, "failed to execute select query")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func insertCommand(req []byte, db *sql.DB) error {
|
||||||
|
q := "INSERT INTO " + table + " SELECT * FROM json_populate_record(null::" + table + ", $1)"
|
||||||
|
_, err := db.Exec(q, req)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Failed to execute insert query")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
10
examples/postgres/glide.lock
generated
Normal file
10
examples/postgres/glide.lock
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
hash: 12ce0fe3e599891c7aeb6d5a99ff107b4f979e88ff5da7a6d5b1cf5cac8b1ad7
|
||||||
|
updated: 2017-01-20T22:48:30.561728713Z
|
||||||
|
imports:
|
||||||
|
- name: github.com/lib/pq
|
||||||
|
version: 67c3f2a8884c9b1aac5503c8d42ae4f73a93511c
|
||||||
|
subpackages:
|
||||||
|
- oid
|
||||||
|
- name: github.com/pkg/errors
|
||||||
|
version: 248dadf4e9068a0b3e79f02ed0a610d935de5302
|
||||||
|
testImports: []
|
||||||
4
examples/postgres/glide.yaml
Normal file
4
examples/postgres/glide.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package: github.com/iron-io/functions/examples/postgres
|
||||||
|
import:
|
||||||
|
- package: github.com/lib/pq
|
||||||
|
- package: github.com/pkg/errors
|
||||||
39
examples/postgres/test.sh
Executable file
39
examples/postgres/test.sh
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x
|
||||||
|
|
||||||
|
docker stop test-postgres-func
|
||||||
|
docker rm test-postgres-func
|
||||||
|
|
||||||
|
docker run -p 5432:5432 --name test-postgres-func -d postgres
|
||||||
|
sleep 5s
|
||||||
|
|
||||||
|
docker run --rm -i --link test-postgres-func:postgres postgres psql -h postgres -U postgres -c 'CREATE TABLE people (first TEXT, last TEXT, age INTEGER);'
|
||||||
|
|
||||||
|
RECORD1='{
|
||||||
|
"first": "John",
|
||||||
|
"last": "Smith",
|
||||||
|
"age": 30
|
||||||
|
}'
|
||||||
|
echo $RECORD1 | fn run -e SERVER=postgres:5432 -e COMMAND=INSERT -e TABLE=people --link test-postgres-func:postgres
|
||||||
|
QUERY1='{
|
||||||
|
"last": "Smith"
|
||||||
|
}'
|
||||||
|
echo $QUERY1 | fn run -e SERVER=postgres:5432 -e COMMAND=SELECT -e TABLE=people --link test-postgres-func:postgres
|
||||||
|
|
||||||
|
RECORD2='{
|
||||||
|
"first": "Bob",
|
||||||
|
"last": "Smith",
|
||||||
|
"age": 43
|
||||||
|
}'
|
||||||
|
echo $RECORD2 | fn run -e SERVER=postgres:5432 -e COMMAND=INSERT -e TABLE=people --link test-postgres-func:postgres
|
||||||
|
|
||||||
|
echo $QUERY1 | fn run -e SERVER=postgres:5432 -e COMMAND=SELECT -e TABLE=people --link test-postgres-func:postgres
|
||||||
|
|
||||||
|
QUERY2='{
|
||||||
|
"first": "John",
|
||||||
|
"last": "Smith"
|
||||||
|
}'
|
||||||
|
echo $QUERY2 | fn run -e SERVER=postgres:5432 -e COMMAND=SELECT -e TABLE=people --link test-postgres-func:postgres
|
||||||
|
|
||||||
|
docker stop test-postgres-func
|
||||||
|
docker rm test-postgres-func
|
||||||
Reference in New Issue
Block a user