query logs
This commit is contained in:
parent
8fc1a84b1b
commit
1869285de4
|
@ -14,7 +14,9 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/facebookgo/flagenv"
|
||||
shell "github.com/ipfs/go-ipfs-api"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
"github.com/perlin-network/life/exec"
|
||||
"github.com/rogpeppe/go-internal/txtar"
|
||||
"tulpa.dev/within/wasmcloud/cmd/internal"
|
||||
|
@ -22,20 +24,26 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ipfsURL = flag.String("ipfs-host", "localhost:5001", "IPFS host (must have pubsub experiment enabled)")
|
||||
natsURL = flag.String("nats-url", nats.DefaultURL, "nats URL")
|
||||
ipfsURL = flag.String("ipfs-host", "localhost:5001", "IPFS host")
|
||||
workerCount = flag.Int("worker-count", 1, "number of wasm executor workers")
|
||||
gasLimit = flag.Int("gas-limit", 1048576, "number of wasm instructions per execution")
|
||||
ramLimit = flag.Int("ram-limit", 128, "number of wasm pages that can be used")
|
||||
loopTimeout = flag.Duration("loop-timeout", 30*time.Second, "idle time per loop")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flagenv.Parse()
|
||||
flag.Parse()
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
|
||||
sh := shell.NewShell(*ipfsURL)
|
||||
subsc, err := sh.PubSubSubscribe(internal.TopicName)
|
||||
|
||||
nc, err := nats.Connect(*natsURL)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
|
@ -53,15 +61,19 @@ func main() {
|
|||
wg.Add(*workerCount)
|
||||
|
||||
for range make([]struct{}, *workerCount) {
|
||||
go waitForNewWASM(ctx, &wg, sh, subsc)
|
||||
go waitForNewWASM(ctx, &wg, sh, nc)
|
||||
}
|
||||
|
||||
log.Printf("waiting for work on %s", internal.TopicName)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func waitForNewWASM(ctx context.Context, wg *sync.WaitGroup, sh *shell.Shell, subsc *shell.PubSubSubscription) {
|
||||
func waitForNewWASM(ctx context.Context, wg *sync.WaitGroup, sh *shell.Shell, nc *nats.Conn) {
|
||||
defer wg.Done()
|
||||
subsc, err := nc.QueueSubscribeSync(internal.TopicName, "workers")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
|
@ -70,8 +82,12 @@ func waitForNewWASM(ctx context.Context, wg *sync.WaitGroup, sh *shell.Shell, su
|
|||
default:
|
||||
}
|
||||
|
||||
msg, err := subsc.Next()
|
||||
msg, err := subsc.NextMsg(*loopTimeout)
|
||||
if err != nil {
|
||||
if err == nats.ErrTimeout {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("error getting message: %v", err)
|
||||
return
|
||||
}
|
||||
|
@ -125,7 +141,7 @@ func waitForNewWASM(ctx context.Context, wg *sync.WaitGroup, sh *shell.Shell, su
|
|||
}
|
||||
|
||||
arc := txtar.Archive{
|
||||
Comment: []byte(fmt.Sprintf("%s: execution of %s at %s", er.UUID, er.WASMCID, result.StartTime.Format(time.RFC3339))),
|
||||
Comment: []byte(fmt.Sprintf("%s: execution of %s (%s) at %s", er.UUID, er.Name, er.WASMCID, result.StartTime.Format(time.RFC3339))),
|
||||
Files: []txtar.File{
|
||||
{
|
||||
Name: "logs.txt",
|
||||
|
@ -162,6 +178,6 @@ func waitForNewWASM(ctx context.Context, wg *sync.WaitGroup, sh *shell.Shell, su
|
|||
UUID: er.UUID,
|
||||
}
|
||||
repMsg, _ := json.Marshal(resp)
|
||||
sh.PubSubPublish(er.UUID, string(repMsg))
|
||||
msg.Respond(repMsg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/google/subcommands"
|
||||
"tulpa.dev/within/wasmcloud/cmd/internal"
|
||||
)
|
||||
|
||||
type handlerCreateCmd struct {
|
||||
abi string
|
||||
}
|
||||
|
||||
func (handlerCreateCmd) Name() string { return "create" }
|
||||
func (handlerCreateCmd) Synopsis() string { return "create a new handler" }
|
||||
func (handlerCreateCmd) Usage() string {
|
||||
return `wasmcloud create [options] <filename.wasm>
|
||||
|
||||
$ wasmcloud create filename.wasm
|
||||
$ wasmcloud create -abi dagger filename.wasm
|
||||
|
||||
Creates a new handler on wasmcloud. Returns a name you can use to invoke the
|
||||
function.
|
||||
|
||||
Flags:
|
||||
`
|
||||
}
|
||||
|
||||
func (h *handlerCreateCmd) SetFlags(fs *flag.FlagSet) {
|
||||
fs.StringVar(&h.abi, "abi", "cwa", "WebAssembly ABI to use for the handler")
|
||||
}
|
||||
|
||||
func (h handlerCreateCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
if fs.NArg() != 1 {
|
||||
fmt.Println("usage: wasmcloud create [options] <filename>")
|
||||
return subcommands.ExitUsageError
|
||||
}
|
||||
|
||||
fname := fs.Arg(0)
|
||||
data, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
hdlr := internal.Handler{
|
||||
ABI: h.abi,
|
||||
WASM: data,
|
||||
}
|
||||
|
||||
bodyData, _ := json.Marshal(hdlr)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, *apiServer+"/api/handler/create", bytes.NewBuffer(bodyData))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
withAPI(req)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
io.Copy(os.Stdout, resp.Body)
|
||||
return subcommands.ExitFailure
|
||||
}
|
||||
|
||||
type apiResp struct {
|
||||
ID int `json:"ID"`
|
||||
CreatedAt time.Time `json:"CreatedAt"`
|
||||
UpdatedAt time.Time `json:"UpdatedAt"`
|
||||
Name string `json:"Name"`
|
||||
Path string `json:"Path"`
|
||||
}
|
||||
|
||||
var result apiResp
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println("created new handler")
|
||||
fmt.Printf("name: %s\nIPFS ID: %s\n", result.Name, result.Path)
|
||||
|
||||
return subcommands.ExitSuccess
|
||||
}
|
|
@ -35,11 +35,13 @@ func (l *loginCmd) SetFlags(fs *flag.FlagSet) {
|
|||
fs.StringVar(&l.username, "username", "", "wasmcloud username")
|
||||
}
|
||||
|
||||
func (l *loginCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
func init() {
|
||||
http.DefaultClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
}
|
||||
|
||||
func (l *loginCmd) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
cfg, err := loadConfig()
|
||||
if err != nil {
|
||||
log.Printf("error loading config: %v", err)
|
||||
|
|
|
@ -20,8 +20,8 @@ func main() {
|
|||
subcommands.Register(subcommands.CommandsCommand(), "")
|
||||
subcommands.Register(&loginCmd{}, "api")
|
||||
subcommands.Register(&whoamiCmd{}, "api")
|
||||
subcommands.Register(&handlerCreateCmd{}, "handlers")
|
||||
subcommands.Register(namegenCmd{}, "utils")
|
||||
subcommands.Register(&testWorkCommand{}, "utils")
|
||||
subcommands.Register(&runCmd{}, "utils")
|
||||
subcommands.ImportantFlag("api-server")
|
||||
subcommands.ImportantFlag("config")
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/google/subcommands"
|
||||
"github.com/google/uuid"
|
||||
shell "github.com/ipfs/go-ipfs-api"
|
||||
"github.com/rogpeppe/go-internal/txtar"
|
||||
"tulpa.dev/within/wasmcloud/cmd/internal"
|
||||
)
|
||||
|
||||
type testWorkCommand struct {
|
||||
wasmCID, abi, ipfsURL string
|
||||
}
|
||||
|
||||
func (testWorkCommand) Name() string { return "test-work" }
|
||||
func (testWorkCommand) Synopsis() string { return "sends a test work message over IPFS" }
|
||||
func (testWorkCommand) Usage() string { return "TODO(within): this" }
|
||||
|
||||
func (t *testWorkCommand) SetFlags(fs *flag.FlagSet) {
|
||||
fs.StringVar(&t.wasmCID, "wasm-cid", "", "CID for the WASM to run")
|
||||
fs.StringVar(&t.abi, "abi", "cwa", "which ABI to use")
|
||||
fs.StringVar(&t.ipfsURL, "ipfs-host", "127.0.0.1:5001", "IPFS host")
|
||||
}
|
||||
|
||||
func (t testWorkCommand) Execute(ctx context.Context, fs *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
sh := shell.NewShell(t.ipfsURL)
|
||||
rdr, err := sh.Cat(t.wasmCID)
|
||||
if err != nil {
|
||||
log.Fatalf("error getting %s: %v", t.wasmCID, err)
|
||||
}
|
||||
io.Copy(ioutil.Discard, rdr)
|
||||
rdr.Close()
|
||||
|
||||
er := internal.ExecRequest{
|
||||
WASMCID: t.wasmCID,
|
||||
ABI: internal.ABI(t.abi),
|
||||
Data: []byte("hello, world"),
|
||||
Env: map[string]string{
|
||||
"MAGIC_CONCH": "yes",
|
||||
},
|
||||
UUID: uuid.New().String(),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(er)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = sh.PubSubPublish(internal.TopicName, string(data))
|
||||
if err != nil {
|
||||
log.Printf("can't publish data: %v", err)
|
||||
return subcommands.ExitFailure
|
||||
}
|
||||
|
||||
subsc, err := sh.PubSubSubscribe(er.UUID)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
msg, err := subsc.Next()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var execResp internal.ExecResponse
|
||||
err = json.Unmarshal(msg.Data, &execResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(txtar.Format(&execResp.Logs)))
|
||||
|
||||
return subcommands.ExitSuccess
|
||||
}
|
|
@ -5,8 +5,12 @@ import (
|
|||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-interpreter/wagon/wasm"
|
||||
"github.com/google/uuid"
|
||||
shell "github.com/ipfs/go-ipfs-api"
|
||||
"github.com/rogpeppe/go-internal/txtar"
|
||||
"tulpa.dev/within/wasmcloud/cmd/internal"
|
||||
"within.website/ln"
|
||||
"within.website/olin/namegen"
|
||||
|
@ -20,7 +24,7 @@ func createHandler(w http.ResponseWriter, r *http.Request, u *User) {
|
|||
|
||||
ctx := r.Context()
|
||||
sh := shell.NewShell(*ipfsURL)
|
||||
data, err := ioutil.ReadAll(r.Body)
|
||||
data, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 16*1024*1024))
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.Error(w, "invalid data", http.StatusBadRequest)
|
||||
|
@ -44,6 +48,13 @@ func createHandler(w http.ResponseWriter, r *http.Request, u *User) {
|
|||
return
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(hdlr.WASM)
|
||||
_, err = wasm.DecodeModule(buf)
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.Error(w, "not webassembly", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
cid, err := sh.Add(bytes.NewBuffer(hdlr.WASM))
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
|
@ -67,3 +78,138 @@ func createHandler(w http.ResponseWriter, r *http.Request, u *User) {
|
|||
|
||||
json.NewEncoder(w).Encode(h)
|
||||
}
|
||||
|
||||
func listHandlers(w http.ResponseWriter, r *http.Request, u *User) {
|
||||
ctx := r.Context()
|
||||
var hdlrs []Handler
|
||||
|
||||
err := db.Where("user_id = ?", u.ID).Scan(&hdlrs).Error
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.Error(w, "can't read handlers", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(hdlrs)
|
||||
}
|
||||
|
||||
func getLogs(w http.ResponseWriter, r *http.Request, u *User) {
|
||||
ctx := r.Context()
|
||||
q := r.URL.Query()
|
||||
name := q.Get("name")
|
||||
if name == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var hdlr Handler
|
||||
err := db.Where("name = ? AND user_id = ?", name, u.ID).First(&hdlr).Error
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var elogs []ExecutionLog
|
||||
err = db.Where("handler_id = ?", hdlr.ID).Find(&elogs).Error
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.Error(w, "handler id not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
type resultLine struct {
|
||||
ExecID string `json:"exec_id"`
|
||||
Comment string `json:"comment"`
|
||||
Logs map[string]string `json:"logs"`
|
||||
}
|
||||
var result []resultLine
|
||||
|
||||
for _, elog := range elogs {
|
||||
arc := txtar.Parse(elog.Data)
|
||||
logs := map[string]string{}
|
||||
|
||||
for _, file := range arc.Files {
|
||||
logs[file.Name] = string(file.Data)
|
||||
}
|
||||
|
||||
result = append(result, resultLine{
|
||||
ExecID: elog.RunID,
|
||||
Comment: string(arc.Comment),
|
||||
Logs: logs,
|
||||
})
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(result)
|
||||
}
|
||||
|
||||
func invokeHandler(w http.ResponseWriter, r *http.Request, u *User) {
|
||||
ctx := r.Context()
|
||||
q := r.URL.Query()
|
||||
name := q.Get("name")
|
||||
if name == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var hdlr Handler
|
||||
err := db.Where("name = ?", name).First(&hdlr).Error
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 1*1024*1024))
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
execID := uuid.New().String()
|
||||
|
||||
er := internal.ExecRequest{
|
||||
WASMCID: hdlr.Path,
|
||||
Name: hdlr.Name,
|
||||
Data: data,
|
||||
Env: map[string]string{
|
||||
"RUN_ID": execID,
|
||||
},
|
||||
UUID: execID,
|
||||
}
|
||||
|
||||
encData, err := json.Marshal(er)
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
go func() {
|
||||
msg, err := nc.Request(internal.TopicName, encData, 5*time.Minute)
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resp internal.ExecResponse
|
||||
err = json.Unmarshal(msg.Data, &resp)
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
data := txtar.Format(&resp.Logs)
|
||||
|
||||
entry := ExecutionLog{
|
||||
HandlerID: hdlr.ID,
|
||||
RunID: execID,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
err = db.Save(&entry).Error
|
||||
if err != nil {
|
||||
ln.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -18,8 +19,10 @@ var (
|
|||
databaseKind = flag.String("database-kind", "sqlite3", "database kind")
|
||||
defaultTokenLifetime = flag.Duration("default-token-lifetime", 500*24*time.Hour, "default token lifetime")
|
||||
ipfsURL = flag.String("ipfs-host", "127.0.0.1:5001", "URL of the IPFS API")
|
||||
natsURL = flag.String("nats-url", nats.DefaultURL, "URL of the nats server")
|
||||
|
||||
db *gorm.DB
|
||||
nc *nats.Conn
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -32,9 +35,15 @@ func main() {
|
|||
}
|
||||
|
||||
log.Println("migrating")
|
||||
gormDB.AutoMigrate(User{}, Token{}, Handler{})
|
||||
gormDB.AutoMigrate(User{}, Token{}, Handler{}, ExecutionLog{})
|
||||
db = gormDB
|
||||
|
||||
natsClient, err := nats.Connect(*natsURL)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
nc = natsClient
|
||||
|
||||
rtr := mux.NewRouter()
|
||||
|
||||
// auth
|
||||
|
@ -46,8 +55,14 @@ func main() {
|
|||
rtr.HandleFunc("/", unauthenticatedShowAPage("index"))
|
||||
rtr.HandleFunc("/control/", authenticatedShowAPage("controlindex"))
|
||||
|
||||
rtr.HandleFunc("/api/whoami", makeHandler(true, apiWhoami))
|
||||
// API routes
|
||||
rtr.HandleFunc("/api/handler", makeHandler(true, listHandlers)).Methods(http.MethodGet)
|
||||
rtr.HandleFunc("/api/handler/create", makeHandler(true, createHandler)).Methods(http.MethodPost)
|
||||
rtr.HandleFunc("/api/handler/logs", makeHandler(true, getLogs)).Methods(http.MethodGet)
|
||||
rtr.HandleFunc("/api/whoami", makeHandler(true, apiWhoami))
|
||||
|
||||
// invocation
|
||||
rtr.HandleFunc("/invoke", makeHandler(false, invokeHandler)).Methods(http.MethodPost)
|
||||
|
||||
rtr.PathPrefix("/static/").Handler(http.FileServer(http.Dir(".")))
|
||||
|
||||
|
|
|
@ -26,10 +26,17 @@ type Token struct {
|
|||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
type ExecutionLog struct {
|
||||
gorm.Model
|
||||
RunID string `gorm:"unique;not null"`
|
||||
HandlerID uint
|
||||
Data []byte `gorm:"not null"`
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
Path string
|
||||
Name string `gorm:"unique;not null"`
|
||||
Path string `gorm:"unique;not null"`
|
||||
UserID uint
|
||||
User User
|
||||
}
|
||||
|
|
3
go.mod
3
go.mod
|
@ -7,6 +7,7 @@ replace github.com/go-interpreter/wagon v0.0.0 => github.com/perlin-network/wago
|
|||
require (
|
||||
github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/go-interpreter/wagon v0.0.0
|
||||
github.com/google/subcommands v1.0.1
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/mux v1.7.3
|
||||
|
@ -15,6 +16,8 @@ require (
|
|||
github.com/jinzhu/gorm v1.9.11
|
||||
github.com/manifoldco/promptui v0.6.0
|
||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible
|
||||
github.com/nats-io/nats-server/v2 v2.1.2 // indirect
|
||||
github.com/nats-io/nats.go v1.9.1
|
||||
github.com/perlin-network/life v0.0.0-20190204091834-d05763d11050
|
||||
github.com/rogpeppe/go-internal v1.5.0
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
|
||||
|
|
18
go.sum
18
go.sum
|
@ -100,6 +100,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
|
@ -230,6 +231,21 @@ github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d
|
|||
github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ=
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server v1.4.1 h1:Ul1oSOGNV/L8kjr4v6l2f9Yet6WY+LevH1/7cRZ/qyA=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDaCRQc=
|
||||
github.com/nicksnyder/go-i18n v1.10.1/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
|
@ -324,6 +340,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -370,6 +387,7 @@ golang.org/x/sys v0.0.0-20190219203350-90b0e4468f99/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
Loading…
Reference in New Issue