Skip to content

Commit

Permalink
initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
emanueldima committed Jul 3, 2015
0 parents commit fac436d
Show file tree
Hide file tree
Showing 8 changed files with 710 additions and 0 deletions.
339 changes: 339 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions README.md
@@ -0,0 +1,4 @@
GEF-Docker
==========

The GEF backend for Docker
153 changes: 153 additions & 0 deletions apiserver.go
@@ -0,0 +1,153 @@
package main

import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"

"../eudock"

"github.com/gorilla/mux"
)

// ErrPreMarshal reports a coding error before marshalling json
var ErrPreMarshal = errors.New("pre-marshalling json error")

// ServerConfig keeps the configuration options needed to make a Server
type ServerConfig struct {
Address string
ReadTimeoutSecs int
WriteTimeoutSecs int
}

// Server is a master struct for serving HTTP API requests
type Server struct {
server http.Server
docker *eudock.Client
}

// NewServer creates a new Server
func NewServer(cfg ServerConfig, docker eudock.Client) *Server {
server := &Server{
http.Server{
Addr: cfg.Address,
// timeouts seem to trigger even after a correct read
// ReadTimeout: cfg.ReadTimeoutSecs * time.Second,
// WriteTimeout: cfg.WriteTimeoutSecs * time.Second,

}, &docker,
}
router := mux.NewRouter()
apirouter := router.PathPrefix("/api").Subrouter()
apirouter.HandleFunc("/", server.listServicesHandler).Methods("GET")
apirouter.HandleFunc("/", server.buildServiceImageHandler).Methods("POST")
apirouter.HandleFunc("/{imageID}", server.inspectServiceHandler).Methods("GET")

server.server.Handler = router
return server
}

// Start starts a new http listener
func (s *Server) Start() error {
return s.server.ListenAndServe()
}

func (s Server) listServicesHandler(w http.ResponseWriter, r *http.Request) {
imgIDs, err := s.docker.ListImages()
if err != nil {
log.Println("ERROR: list of docker images: ", err)
s.serverError(w, err)
return
}
s.okJMap(w, "ImageIDs", imgIDs)
}

func (s Server) inspectServiceHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
imageID := eudock.ImageID(vars["imageID"])
image, err := s.docker.InspectImage(imageID)
if err != nil {
log.Println("ERROR: inspect docker image: ", err)
s.serverError(w, err)
return
}
srv := extractServiceInfo(image.Labels)
s.okJMap(w, "Image", image, "Service", srv)
}

func (s Server) buildServiceImageHandler(w http.ResponseWriter, r *http.Request) {
image, err := s.docker.BuildImage("../gef-service-example")
if err != nil {
log.Println("ERROR: build docker image: ", err)
s.serverError(w, err)
return
}
s.okJMap(w, "Image", image)
}

func (s Server) executeServiceHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
imageID := eudock.ImageID(vars["imageID"])
container, err := s.docker.ExecuteImage(imageID)
if err != nil {
log.Println("ERROR: execute docker image: ", err)
s.serverError(w, err)
return
}
s.okJMap(w, "ContainerID", container.ID)
}

func (s Server) okJMap(w http.ResponseWriter, kv ...interface{}) {
if len(kv) == 0 {
log.Println("ERROR: jsonmap: empty call")
s.serverError(w, ErrPreMarshal)
return
} else if len(kv)%2 == 1 {
log.Println("ERROR: jsonmap: unbalanced call")
s.serverError(w, ErrPreMarshal)
return
}
m := make(map[string]interface{})
k := ""
for _, kv := range kv {
if k == "" {
if skv, ok := kv.(string); !ok {
log.Println("ERROR: jsonmap: expected string key")
s.serverError(w, ErrPreMarshal)
return
} else if skv == "" {
log.Println("ERROR: jsonmap: string key is empty")
s.serverError(w, ErrPreMarshal)
return
} else {
k = skv
}
} else {
m[k] = kv
k = ""
}
}
s.okJSON(w, m)
}

func (s Server) okJSON(w http.ResponseWriter, data interface{}) {
json, err := json.Marshal(data)
if err != nil {
log.Println("ERROR: json marshal: ", err)
s.serverError(w, err)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(json)
}

func (s Server) serverError(w http.ResponseWriter, err error) {
http.Error(w, fmt.Sprintln("Server Error: ", err), 500)
}

// func notFoundHandler(w http.ResponseWriter, r *http.Request) {
// w.Header().Set("Content-Type", "text/plain; charset=utf-8")
// w.Write([]byte("Resource not found"))
// }
42 changes: 42 additions & 0 deletions build.sh
@@ -0,0 +1,42 @@
#!/bin/bash

BUILD=1
RUN=

while [[ $# > 0 ]]
do
key="$1"
# echo $# " :" $key
case $key in
--build)
BUILD=1
;;
--run)
RUN=1
;;
*)
echo "Unknown option:" $1
exit 1
;;
esac
shift
done

if [ $BUILD ]
then
echo; echo "---- go lint"
golint ./...
echo; echo "---- go vet"
go vet ./...
echo; echo "---- go build"
go build
fi

if [ $RUN ]
then
echo; echo "---- run devel"
# echo "-- vagrant up"
# (cd vagrant && vagrant up)
echo "-- ./gef-docker"
"./gef-docker"
fi
25 changes: 25 additions & 0 deletions config.go
@@ -0,0 +1,25 @@
package main

import (
"encoding/json"
"os"

"../eudock"
)

type configuration struct {
Docker []eudock.Config
Server ServerConfig
}

func readConfigFile(configfilepath string) (configuration, error) {
var config configuration
file, err := os.Open(configfilepath)
if err != nil {
return config, err
}
defer file.Close()
decoder := json.NewDecoder(file)
err = decoder.Decode(&config)
return config, err
}
16 changes: 16 additions & 0 deletions config.json
@@ -0,0 +1,16 @@
{
"Docker": [
{
"Endpoint" : "unix:///var/run/docker.sock"
},
{
"UseBoot2Docker": true,
"Description": "Using Boot2Docker with its environment variables: $DOCKER_HOST and $DOCKER_CERT_PATH"
}
],
"Server": {
"Address": ":4142",
"ReadTimeoutSecs": 10,
"WriteTimeoutSecs": 10
}
}
95 changes: 95 additions & 0 deletions gefservice.go
@@ -0,0 +1,95 @@
package main

import (
"log"
"strconv"
"strings"
)

// GefSrvLabelPrefix is the prefix identifying GEF related labels
const GefSrvLabelPrefix = "eudat.gef.service."

// Service describes metadata for a GEF service
type Service struct {
Name string
Description string
Version string
Input []IOPort
Output []IOPort
}

// IOPort is an i/o specification for a service
type IOPort struct {
Path string
}

///////////////////////////////////////////////////////////////////////////////

func extractServiceInfo(labels map[string]string) Service {
srv := Service{}

for k, v := range labels {
if !strings.HasPrefix(k, GefSrvLabelPrefix) {
continue
}
k = k[len(GefSrvLabelPrefix):]
// fmt.Println(k, " -> ", v)
ks := strings.Split(k, ".")
if len(ks) == 0 {
continue
}
switch ks[0] {
case "name":
srv.Name = v
case "description":
srv.Description = v
case "version":
srv.Version = v
case "input":
addVecValue(&srv.Input, ks[1:], v)
case "output":
addVecValue(&srv.Output, ks[1:], v)
default:
log.Println("Unknown GEF service label: ", k, "=", v)
}
}

{
in := make([]IOPort, 0, len(srv.Input))
for _, p := range srv.Input {
if p.Path != "" {
in = append(in, p)
}
}
srv.Input = in
}
{
out := make([]IOPort, 0, len(srv.Output))
for _, p := range srv.Output {
if p.Path != "" {
out = append(out, p)
}
}
srv.Output = out
}
return srv
}

func addVecValue(vec *[]IOPort, ks []string, value string) {
if len(ks) == 0 {
log.Println("ERROR: GEF service label I/O key empty")
return
}
if len(ks) > 1 {
log.Println("ERROR: GEF service label I/O key has too many parts: ", ks)
return
}
id, err := strconv.ParseUint(ks[0], 10, 8)
if err != nil {
log.Println("ERROR: GEF service label: expecting integer argument for IOPort, instead got: ", ks)
}
for len(*vec) < int(id)+1 {
*vec = append(*vec, IOPort{})
}
(*vec)[id].Path = value
}
36 changes: 36 additions & 0 deletions main.go
@@ -0,0 +1,36 @@
package main

import (
"flag"

"../eudock"
)
import "log"

var configFilePath = "config.json"

var config configuration

func main() {
flag.StringVar(&configFilePath, "config", configFilePath, "configuration file")
flag.Parse()

var err error
config, err = readConfigFile(configFilePath)
if err != nil {
log.Fatal("FATAL while reading config files: ", err)
}
if len(config.Docker) == 0 {
log.Fatal("FATAL: empty docker configuration list:\n", config)
}

client, err := eudock.NewClientFirstOf(config.Docker)
if err != nil {
log.Print(err)
log.Fatal("Failed to make any docker client, exiting")
}

server := NewServer(config.Server, client)
log.Println("Starting GEF server at: ", config.Server.Address)
server.Start()
}

0 comments on commit fac436d

Please sign in to comment.