Code imported from @CesarGallego private repo

This commit is contained in:
Roberto Abdelkader Martínez Pérez
2019-10-02 15:49:16 +02:00
parent e146ec6647
commit 3602dc71f2
10 changed files with 328 additions and 22 deletions
+30
View File
@@ -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
}
+66
View File
@@ -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")
}
}
+31
View File
@@ -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
}
+11
View File
@@ -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()
}
}
+34
View File
@@ -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")
}
+52
View File
@@ -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)
}
+38
View File
@@ -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
}
+26
View File
@@ -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")
}
+25
View File
@@ -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
}
+15 -22
View File
@@ -2,31 +2,24 @@ package main
import (
"fmt"
b "github.com/BBVA/kapow/pkg/banner"
"net/http"
"os"
"github.com/spf13/cobra"
"github.com/BBVA/kapow/command"
)
func main() {
ban := b.Banner("0.1.0")
fmt.Println(ban)
var kapowCmd = &cobra.Command{Use: "kapow [action]"}
go func() {
http.ListenAndServe(":8080", &userServerHandler{})
}()
http.ListenAndServe(":8081", &controlAPIHandler{})
kapowCmd.AddCommand(command.ServerCmd)
kapowCmd.AddCommand(command.GetCmd)
kapowCmd.AddCommand(command.SetCmd)
kapowCmd.AddCommand(command.RouteCmd)
}
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)
err := kapowCmd.Execute()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}