Skip to content

Instantly share code, notes, and snippets.

@mhrivnak
Last active August 3, 2018 14:06
Show Gist options
  • Save mhrivnak/624e75fce1dadf93ea5c5bb27955a05b to your computer and use it in GitHub Desktop.
Save mhrivnak/624e75fce1dadf93ea5c5bb27955a05b to your computer and use it in GitHub Desktop.
package main
/*
Run this service, then make http requests to the unix socket at path /events/
Each request must:
- use method POST
- include a JSON body
The request body will be printed for human inspection.
*/
import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
// EventTime - time to unmarshal nano time.
type EventTime struct {
time.Time
}
// UnmarshalJSON - override unmarshal json.
func (e *EventTime) UnmarshalJSON(b []byte) (err error) {
e.Time, err = time.Parse("2006-01-02T15:04:05.999999999", strings.Trim(string(b[:]), "\"\\"))
if err != nil {
return err
}
return nil
}
// JobEvent - event of an ansible run.
type JobEvent struct {
UUID string `json:"uuid"`
Counter int `json:"counter"`
StdOut string `json:"stdout"`
StartLine int `json:"start_line"`
EndLine int `json:"EndLine"`
Event string `json:"event"`
EventData map[string]interface{} `json:"event_data"`
PID int `json:"pid"`
Created EventTime `json:"created"`
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "/path/to/new/socket")
os.Exit(1)
}
path := os.Args[1]
listener, err := net.Listen("unix", path)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
defer listener.Close()
mux := http.NewServeMux()
mux.HandleFunc("events/", handleEvents)
go http.Serve(listener, mux)
// give the listener a chance to close before exiting
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
}
func handleEvents(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
ct := r.Header.Get("content-type")
if strings.Split(ct, ";")[0] != "application/json" {
w.WriteHeader(http.StatusUnsupportedMediaType)
w.Write([]byte("The content-type must be \"application/json\""))
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
fmt.Println(string(body))
event := JobEvent{}
err = json.Unmarshal(body, &event)
if err != nil {
fmt.Println(err.Error())
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Could not deserialize body as JSON"))
return
}
w.WriteHeader(http.StatusNoContent)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment