Code imported from @CesarGallego private repo
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getReason(r *http.Response) string {
|
||||||
|
return strings.Join(strings.Split(r.Status, " ")[1:], " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetData will perform the request and write the results on the provided writer
|
||||||
|
func GetData(host, id, path string, wr io.Writer) error {
|
||||||
|
url := host + "/handlers/" + id + path
|
||||||
|
|
||||||
|
res, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
if res.StatusCode < 200 || res.StatusCode >= 300 {
|
||||||
|
return errors.New(getReason(res))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(wr, res.Body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
gock "gopkg.in/h2non/gock.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetInvalidUrl(t *testing.T) {
|
||||||
|
err := GetData("", "", "", os.Stdout)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with invalid url ''")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetInvalidWriter(t *testing.T) {
|
||||||
|
err := GetData("http://localhost:8081", "0000", "/", nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with no writer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetURLNotFoundWithUnknownID(t *testing.T) {
|
||||||
|
defer gock.Off()
|
||||||
|
|
||||||
|
gock.New("http://localhost:8081").
|
||||||
|
Get("/handlers/000/").Reply(http.StatusNotFound)
|
||||||
|
|
||||||
|
err := GetData("http://localhost:8081", "000", "/", os.Stdout)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expect not found error but get no error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if gock.IsDone() == false {
|
||||||
|
t.Error("No expected endpoint called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRetrieveRequestMethod(t *testing.T) {
|
||||||
|
defer gock.Off()
|
||||||
|
|
||||||
|
gock.New("http://localhost:8081").
|
||||||
|
Get("/handlers/000/request/method").
|
||||||
|
Reply(http.StatusAccepted).
|
||||||
|
BodyString("POST")
|
||||||
|
|
||||||
|
rw := new(bytes.Buffer)
|
||||||
|
|
||||||
|
err := GetData("http://localhost:8081", "000", "/request/method", rw)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error %v", err)
|
||||||
|
}
|
||||||
|
strRes := rw.String()
|
||||||
|
|
||||||
|
if strRes != "POST" {
|
||||||
|
t.Errorf("POST string expected but found: '%v'", strRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if gock.IsDone() == false {
|
||||||
|
t.Error("No expected endpoint called")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddRoute will add a new route in kapow
|
||||||
|
func AddRoute(host, path, method, entrypoint, command string) error {
|
||||||
|
reqData, err := http.NewRequest(
|
||||||
|
"PUT",
|
||||||
|
host+"/routes",
|
||||||
|
strings.NewReader(command),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var client = new(http.Client)
|
||||||
|
res, err := client.Do(reqData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode < 200 || res.StatusCode >= 300 {
|
||||||
|
return errors.New(res.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestInvalidURL(t *testing.T) {
|
||||||
|
err := AddRoute("http://localhost;8080", "/hi", "GET", "bash -c", "echo 'Hi' | kapow set /response/body")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expect to fail due invalid url")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/BBVA/kapow/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCmd is the command line interface for get kapow data operation
|
||||||
|
var GetCmd = &cobra.Command{
|
||||||
|
Use: "get [flags] resource",
|
||||||
|
Short: "Retrive a Kapow! resource",
|
||||||
|
Long: "Retrive a Kapow! resource for the current request",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
PreRunE: handlerIDRequired,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url, _ := cmd.Flags().GetString("url")
|
||||||
|
handler, _ := cmd.Flags().GetString("handler")
|
||||||
|
|
||||||
|
err := client.GetData(url, handler, args[0], os.Stdout)
|
||||||
|
if err != nil {
|
||||||
|
os.Stderr.WriteString(fmt.Sprintf("%v\n", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
GetCmd.Flags().String("url", getEnv("KAPOW_URL", "http://localhost:8082"), "Kapow! data interface URL")
|
||||||
|
GetCmd.Flags().String("handler", getEnv("KAPOW_HANDLER_ID", ""), "Kapow! handler id")
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
//RouteCmd is the command line interface for kapow route manipulation
|
||||||
|
var RouteCmd = &cobra.Command{
|
||||||
|
Use: "route [action]",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var routeListCmd = &cobra.Command{
|
||||||
|
Use: "list [flags]",
|
||||||
|
Short: "List the current Kapow! routes",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url, _ := cmd.Flags().GetString("url")
|
||||||
|
fmt.Println("niano: ", url)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
routeListCmd.Flags().String("url", getEnv("KAPOW_URL", "http://localhost:8082"), "Kapow! data interface URL")
|
||||||
|
|
||||||
|
var routeAddCmd = &cobra.Command{
|
||||||
|
Use: "add [flags] url_pattern [command_file]",
|
||||||
|
Short: "Add a route",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url, _ := cmd.Flags().GetString("url")
|
||||||
|
fmt.Println("niano: ", url)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
routeAddCmd.Flags().String("url", getEnv("KAPOW_URL", "http://localhost:8082"), "Kapow! data interface URL")
|
||||||
|
routeAddCmd.Flags().StringP("command", "c", "", "Command to pass to the shell")
|
||||||
|
routeAddCmd.Flags().StringP("entrypoint", "e", "", "Command to execute")
|
||||||
|
routeAddCmd.Flags().StringP("method", "X", "", "HTTP method to accept")
|
||||||
|
|
||||||
|
var routeRemoveCmd = &cobra.Command{
|
||||||
|
Use: "remove [flags] route_id",
|
||||||
|
Short: "Remove the given route",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url, _ := cmd.Flags().GetString("url")
|
||||||
|
fmt.Println("niano: ", url)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
routeRemoveCmd.Flags().String("url", getEnv("KAPOW_URL", "http://localhost:8082"), "Kapow! data interface URL")
|
||||||
|
|
||||||
|
RouteCmd.AddCommand(routeListCmd)
|
||||||
|
RouteCmd.AddCommand(routeAddCmd)
|
||||||
|
RouteCmd.AddCommand(routeRemoveCmd)
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServerCmd is the command line interface for kapow server
|
||||||
|
var ServerCmd = &cobra.Command{
|
||||||
|
Use: "server [optional flags] [optional pow file(s)]",
|
||||||
|
Short: "Start a kapow server",
|
||||||
|
Long: `Start a Kapow server with, by default with client interface, data interface
|
||||||
|
and admin interface`,
|
||||||
|
PreRunE: validateServerCommandArguments,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cert, _ := cmd.Flags().GetString("certfile")
|
||||||
|
key, _ := cmd.Flags().GetString("keyfile")
|
||||||
|
fmt.Println("waka server feliz :)", cert, key)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ServerCmd.Flags().String("certfile", "", "Cert file to serve thru https")
|
||||||
|
ServerCmd.Flags().String("keyfile", "", "Key file to serve thru https")
|
||||||
|
ServerCmd.Flags().String("bind", "", "IP address and port to listen to")
|
||||||
|
ServerCmd.Flags().BoolP("interactive", "i", false, "Boot an empty kapow server with a shell")
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateServerCommandArguments(cmd *cobra.Command, args []string) error {
|
||||||
|
cert, _ := cmd.Flags().GetString("certfile")
|
||||||
|
key, _ := cmd.Flags().GetString("keyfile")
|
||||||
|
if (cert == "") != (key == "") {
|
||||||
|
return errors.New("expected both or neither (certfile and keyfile)")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
//SetCmd is the command line interface for set kapow data operation
|
||||||
|
var SetCmd = &cobra.Command{
|
||||||
|
Use: "set [flags] resource [value]",
|
||||||
|
Short: "Set a Kapow! resource value",
|
||||||
|
Long: "Set a Kapow! resource value for the current request",
|
||||||
|
Args: cobra.RangeArgs(1, 2),
|
||||||
|
PreRunE: handlerIDRequired,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url, _ := cmd.Flags().GetString("url")
|
||||||
|
handler, _ := cmd.Flags().GetString("handler")
|
||||||
|
fmt.Println("niano: ", url, handler)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SetCmd.Flags().String("url", getEnv("KAPOW_URL", "http://localhost:8082"), "Kapow! data interface URL")
|
||||||
|
SetCmd.Flags().String("handler", getEnv("KAPOW_HANDLER_ID", ""), "Kapow! handler id")
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getEnv(key, fallback string) string {
|
||||||
|
value, exists := os.LookupEnv(key)
|
||||||
|
if !exists {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlerIDRequired(cmd *cobra.Command, args []string) error {
|
||||||
|
handler, _ := cmd.Flags().GetString("handler")
|
||||||
|
if handler == "" {
|
||||||
|
return errors.New("--handler or KAPOW_HANDLER_ID is mandatory")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,31 +2,24 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
b "github.com/BBVA/kapow/pkg/banner"
|
"os"
|
||||||
"net/http"
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/BBVA/kapow/command"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ban := b.Banner("0.1.0")
|
var kapowCmd = &cobra.Command{Use: "kapow [action]"}
|
||||||
fmt.Println(ban)
|
|
||||||
|
|
||||||
go func() {
|
kapowCmd.AddCommand(command.ServerCmd)
|
||||||
http.ListenAndServe(":8080", &userServerHandler{})
|
kapowCmd.AddCommand(command.GetCmd)
|
||||||
}()
|
kapowCmd.AddCommand(command.SetCmd)
|
||||||
http.ListenAndServe(":8081", &controlAPIHandler{})
|
kapowCmd.AddCommand(command.RouteCmd)
|
||||||
|
|
||||||
|
err := kapowCmd.Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
type userServerHandler struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *userServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusNotImplemented)
|
|
||||||
}
|
|
||||||
|
|
||||||
type controlAPIHandler struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *controlAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusNotImplemented)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user