cmd/wasmcloud: more functionality

This commit is contained in:
Cadey Ratio 2019-12-10 23:57:07 +00:00
parent 6b1a8165df
commit d42037eb5a
8 changed files with 198 additions and 7 deletions

View File

@ -0,0 +1,76 @@
package main
import (
"bytes"
"context"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/google/subcommands"
)
type handlerInvokeCmd struct {
fin string
}
func (hic *handlerInvokeCmd) SetFlags(fs *flag.FlagSet) {
fs.StringVar(&hic.fin, "i", "", "input file to pipe to wasmcloud")
}
func (handlerInvokeCmd) Name() string { return "invoke" }
func (handlerInvokeCmd) Synopsis() string { return "synchronously invoke a handler on wasmcloud" }
func (handlerInvokeCmd) Usage() string {
return `wasmcloud invoke <name>
$ wasmcloud invoke princess-of-wands-4018
Invokes a given handler with input read from the given file. Use /dev/stdin
if you want to pipe things.
Flags:
`
}
func (hic handlerInvokeCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
if fs.NArg() != 1 {
fmt.Println("usage: wasmcloud invoke <handler-name>")
return subcommands.ExitUsageError
}
hname := fs.Arg(0)
var buf = bytes.NewBuffer(nil)
if hic.fin != "" {
data, err := ioutil.ReadFile(hic.fin)
if err != nil {
log.Fatal(err)
}
buf = bytes.NewBuffer(data)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, *apiServer+"/invoke/sync?name="+hname+"&whole-bundle=true", buf)
if err != nil {
log.Fatal(err)
}
withAPI(req)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
io.Copy(os.Stdout, resp.Body)
return subcommands.ExitFailure
}
io.Copy(os.Stdout, resp.Body)
return subcommands.ExitSuccess
}

View File

@ -0,0 +1,90 @@
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"time"
"github.com/google/subcommands"
"github.com/gosuri/uitable"
)
type handlerListCmd struct {
format string
}
func (h *handlerListCmd) SetFlags(fs *flag.FlagSet) {
fs.StringVar(&h.format, "format", "table", "what format to present output in (table|json)")
}
func (handlerListCmd) Name() string { return "list" }
func (handlerListCmd) Synopsis() string { return "lists handlers you've created" }
func (handlerListCmd) Usage() string {
return `wasmcloud list [options]
$ wasmcloud list
$ wasmcloud list -format json
Shows all of the handlers you have registered with wasmcloud.
Flags:`
}
func (h handlerListCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, *apiServer+"/api/handler", nil)
if err != nil {
log.Fatal(err)
}
withAPI(req)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
io.Copy(os.Stdout, resp.Body)
return subcommands.ExitFailure
}
switch h.format {
case "json":
io.Copy(os.Stdout, resp.Body)
return subcommands.ExitSuccess
case "table":
type apiResp struct {
CreatedAt time.Time `json:"CreatedAt"`
UpdatedAt time.Time `json:"UpdatedAt"`
Name string `json:"Name"`
CID string `json:"Path"`
}
var result []apiResp
err = json.NewDecoder(resp.Body).Decode(&result)
if err != nil {
log.Fatal(err)
}
table := uitable.New()
table.AddRow("Name", "Created at", "Updated at", "CID")
for _, hdlr := range result {
table.AddRow(
hdlr.Name,
hdlr.CreatedAt.Format(time.RFC3339),
hdlr.UpdatedAt.Format(time.RFC3339),
hdlr.CID,
)
}
fmt.Println(table.String())
}
return subcommands.ExitSuccess
}

View File

@ -31,12 +31,14 @@ func (handlerLogsCmd) Usage() string {
$ wasmcloud logs four-of-aether-60037
Returns all of the logs for a handler.
Flags:
`
}
func (h handlerLogsCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
if fs.NArg() != 1 {
fmt.Println("usage: wasmcloud create [options] <filename>")
fmt.Println("usage: wasmcloud logs [options] <handler-name>")
return subcommands.ExitUsageError
}

View File

@ -18,12 +18,18 @@ func main() {
subcommands.Register(subcommands.HelpCommand(), "")
subcommands.Register(subcommands.FlagsCommand(), "")
subcommands.Register(subcommands.CommandsCommand(), "")
subcommands.Register(&loginCmd{}, "api")
subcommands.Register(&whoamiCmd{}, "api")
subcommands.Register(&handlerCreateCmd{}, "handlers")
subcommands.Register(&handlerListCmd{}, "handlers")
subcommands.Register(&handlerLogsCmd{}, "handlers")
subcommands.Register(&handlerInvokeCmd{}, "handlers")
subcommands.Register(namegenCmd{}, "utils")
subcommands.Register(&runCmd{}, "utils")
subcommands.ImportantFlag("api-server")
subcommands.ImportantFlag("config")

View File

@ -103,7 +103,7 @@ func (r runCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{})
}
arc := txtar.Archive{
Comment: []byte(fmt.Sprintf("execution of %s at %s", fname, result.StartTime.Format(time.RFC3339))),
Comment: []byte(fmt.Sprintf("execution of %s at %s", filepath.Base(fname), result.StartTime.Format(time.RFC3339))),
Files: []txtar.File{
{
Name: "logs.txt",
@ -117,7 +117,7 @@ func (r runCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{})
Name: "stderr.txt",
Data: stderr.Bytes(),
},
result.ToFile(),
result.StatsFile(),
},
}

View File

@ -12,6 +12,7 @@ import (
"time"
"github.com/google/subcommands"
"github.com/gosuri/uitable"
)
type whoamiCmd struct {
@ -71,6 +72,13 @@ func (w *whoamiCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interfac
panic(err)
}
fmt.Printf("Username: %s\nEmail: %s\nIs Admin: %v\nCan Create Handlers: %v\n", result.Username, result.Email, result.IsAdmin, result.CanCreateHandlers)
table := uitable.New()
table.AddRow("Username", result.Username)
table.AddRow("Email", result.Email)
table.AddRow("Is Admin", fmt.Sprint(result.IsAdmin))
table.AddRow("Can Create Handlers", fmt.Sprint(result.CanCreateHandlers))
fmt.Println(table.String())
return subcommands.ExitSuccess
}

View File

@ -12,6 +12,7 @@ import (
"github.com/rogpeppe/go-internal/txtar"
"tulpa.dev/within/wasmcloud/cmd/internal"
"within.website/ln"
"within.website/ln/opname"
"within.website/olin/namegen"
)
@ -80,9 +81,10 @@ func createHandler(w http.ResponseWriter, r *http.Request, u *User) {
func listHandlers(w http.ResponseWriter, r *http.Request, u *User) {
ctx := r.Context()
ctx = opname.With(ctx, "read-handlers")
var hdlrs []Handler
err := db.Where("user_id = ?", u.ID).Scan(&hdlrs).Error
err := db.Where("user_id = ?", u.ID).Find(&hdlrs).Error
if err != nil {
ln.Error(ctx, err)
http.Error(w, "can't read handlers", http.StatusInternalServerError)
@ -150,6 +152,7 @@ func invokeHandlerSync(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
return
}
wholeBundle := q.Get("whole-bundle") == "true"
var hdlr Handler
err := db.Where("name = ?", name).First(&hdlr).Error
@ -186,6 +189,12 @@ func invokeHandlerSync(w http.ResponseWriter, r *http.Request) {
ln.Log(ctx, ln.Action("saving-logs"))
if wholeBundle {
w.Header().Set("Content-Type", "application/txtar")
w.Write(logData)
return
}
for _, file := range resp.Logs.Files {
if file.Name == "stdout.txt" {
w.Write(file.Data)

View File

@ -37,8 +37,8 @@ type Handler struct {
gorm.Model
Name string `gorm:"unique;not null"`
Path string `gorm:"unique;not null"`
UserID uint
User User
UserID uint `json:"-"`
User User `json:"-"`
}
func (t Token) ToCookie() *http.Cookie {