web api, orphaned connections detector, null driver -> nil driver, refactor root command
This commit is contained in:
parent
b89011c631
commit
33290aa5c7
112
cmd/root.go
112
cmd/root.go
@ -6,12 +6,14 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/api"
|
"github.com/Neur0toxine/sshpoke/internal/api/plugin"
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/api/web"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/config"
|
"github.com/Neur0toxine/sshpoke/internal/config"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/docker"
|
"github.com/Neur0toxine/sshpoke/internal/docker"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/logger"
|
"github.com/Neur0toxine/sshpoke/internal/logger"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server"
|
"github.com/Neur0toxine/sshpoke/internal/server"
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
||||||
|
plugin2 "github.com/Neur0toxine/sshpoke/pkg/plugin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -28,53 +30,23 @@ var rootCmd = &cobra.Command{
|
|||||||
Short: "Expose your Docker services to the Internet via SSH.",
|
Short: "Expose your Docker services to the Internet via SSH.",
|
||||||
Long: `sshpoke is a CLI application that listens to the docker socket and automatically exposes relevant services to the Internet.`,
|
Long: `sshpoke is a CLI application that listens to the docker socket and automatically exposes relevant services to the Internet.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
go api.StartPluginAPI()
|
|
||||||
var err error
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
server.DefaultManager = server.NewManager(ctx, config.Default.Servers, config.Default.DefaultServer)
|
server.DefaultManager = server.NewManager(ctx, config.Default.Servers, config.Default.DefaultServer)
|
||||||
docker.Default, err = docker.New(ctx)
|
runPluginServer()
|
||||||
if err != nil {
|
runWebServer()
|
||||||
logger.Sugar.Fatalf("cannot connect to docker daemon: %s", err)
|
runDockerEventListener(ctx)
|
||||||
}
|
shutdown := makeShutdownFunc(cancel)
|
||||||
|
|
||||||
for id, item := range docker.Default.Containers() {
|
|
||||||
err := server.DefaultManager.ProcessEvent(dto.Event{
|
|
||||||
Type: dto.EventStart,
|
|
||||||
Container: item,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
logger.Sugar.Errorw("cannot expose container", "id", id, "error", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
events, err := docker.Default.Listen()
|
|
||||||
if err != nil {
|
|
||||||
logger.Sugar.Fatalf("cannot listen to docker events: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
logger.Sugar.Debug("listening for docker events...")
|
|
||||||
for event := range events {
|
|
||||||
err := server.DefaultManager.ProcessEvent(event)
|
|
||||||
if err != nil {
|
|
||||||
logger.Sugar.Errorw("cannot expose container",
|
|
||||||
"id", event.Container.ID, "error", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
linuxSig := make(chan os.Signal, 1)
|
linuxSig := make(chan os.Signal, 1)
|
||||||
signal.Notify(linuxSig)
|
signal.Notify(linuxSig)
|
||||||
for sig := range linuxSig {
|
for sig := range linuxSig {
|
||||||
switch sig {
|
switch sig {
|
||||||
case os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM:
|
case os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM:
|
||||||
cancel()
|
shutdown(sig)
|
||||||
server.DefaultManager.WaitForShutdown()
|
|
||||||
logger.Sugar.Infof("received %s, exiting...", sig)
|
|
||||||
os.Exit(0)
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
shutdown(syscall.SIGHUP)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +88,72 @@ func initConfig() {
|
|||||||
if err := validator.New().Struct(config.Default); err != nil {
|
if err := validator.New().Struct(config.Default); err != nil {
|
||||||
log.Fatalf("invalid configuration: %s", err)
|
log.Fatalf("invalid configuration: %s", err)
|
||||||
}
|
}
|
||||||
|
if config.Default.API.Web.Port == 0 {
|
||||||
|
config.Default.API.Web.Port = web.DefaultPort
|
||||||
|
}
|
||||||
|
if config.Default.API.Plugin.Port == 0 {
|
||||||
|
config.Default.API.Plugin.Port = plugin2.DefaultPort
|
||||||
|
}
|
||||||
logger.Initialize()
|
logger.Initialize()
|
||||||
logger.Sugar.Debugw("configuration loaded", "config", config.Default)
|
logger.Sugar.Debugw("configuration loaded", "config", config.Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runPluginServer() {
|
||||||
|
port := config.Default.API.Plugin.Port
|
||||||
|
if port == 0 {
|
||||||
|
port = plugin2.DefaultPort
|
||||||
|
}
|
||||||
|
go plugin.StartServer(port, logger.Sugar.With("component", "pluginServer"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func runWebServer() {
|
||||||
|
port := config.Default.API.Web.Port
|
||||||
|
if port == 0 {
|
||||||
|
port = web.DefaultPort
|
||||||
|
}
|
||||||
|
go web.StartServer(
|
||||||
|
config.Default.API.Web.Token, port, logger.Sugar.With("component", "webServer"), config.Default.Debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDockerEventListener(ctx context.Context) {
|
||||||
|
var err error
|
||||||
|
docker.Default, err = docker.New(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Sugar.Fatalf("cannot connect to docker daemon: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for id, item := range docker.Default.Containers() {
|
||||||
|
err := server.DefaultManager.ProcessEvent(dto.Event{
|
||||||
|
Type: dto.EventStart,
|
||||||
|
Container: item,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Sugar.Errorw("cannot expose container", "id", id, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events, err := docker.Default.Listen()
|
||||||
|
if err != nil {
|
||||||
|
logger.Sugar.Fatalf("cannot listen to docker events: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
logger.Sugar.Debug("listening for docker events...")
|
||||||
|
for event := range events {
|
||||||
|
err := server.DefaultManager.ProcessEvent(event)
|
||||||
|
if err != nil {
|
||||||
|
logger.Sugar.Errorw("cannot expose container",
|
||||||
|
"id", event.Container.ID, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeShutdownFunc(cancel func()) func(os.Signal) {
|
||||||
|
return func(sig os.Signal) {
|
||||||
|
cancel()
|
||||||
|
server.DefaultManager.WaitForShutdown()
|
||||||
|
logger.Sugar.Infof("received %s, exiting...", sig)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -153,5 +153,5 @@ servers:
|
|||||||
# This token will be used by plugin while connecting to gRPC API.
|
# This token will be used by plugin while connecting to gRPC API.
|
||||||
token: key
|
token: key
|
||||||
- name: noop
|
- name: noop
|
||||||
# Null driver doesn't do anything. This driver will automatically be used for servers with invalid 'driver' value.
|
# Nil driver doesn't do anything. This driver will automatically be used for servers with invalid 'driver' value.
|
||||||
driver: null
|
driver: nil
|
||||||
|
16
go.mod
16
go.mod
@ -6,10 +6,13 @@ require (
|
|||||||
github.com/docker/docker v24.0.7+incompatible
|
github.com/docker/docker v24.0.7+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/function61/gokit v0.0.0-20231117065306-355fe206d542
|
github.com/function61/gokit v0.0.0-20231117065306-355fe206d542
|
||||||
|
github.com/gin-contrib/secure v0.0.1
|
||||||
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/go-playground/validator/v10 v10.16.0
|
github.com/go-playground/validator/v10 v10.16.0
|
||||||
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8
|
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8
|
||||||
github.com/kevinburke/ssh_config v1.2.0
|
github.com/kevinburke/ssh_config v1.2.0
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
|
github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644
|
||||||
github.com/spf13/cast v1.5.1
|
github.com/spf13/cast v1.5.1
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
github.com/spf13/viper v1.17.0
|
github.com/spf13/viper v1.17.0
|
||||||
@ -24,33 +27,46 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
github.com/changkun/lockfree v0.0.1 // indirect
|
github.com/changkun/lockfree v0.0.1 // indirect
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
github.com/distribution/reference v0.5.0 // indirect
|
github.com/distribution/reference v0.5.0 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/rs/cors v1.8.1 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.10.0 // indirect
|
github.com/spf13/afero v1.10.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
|
55
go.sum
55
go.sum
@ -42,9 +42,15 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
|
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||||
|
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/changkun/lockfree v0.0.1 h1:5WefVJLglY4IHRqOQmh6Ao6wkJYaJkarshKU8VUtId4=
|
github.com/changkun/lockfree v0.0.1 h1:5WefVJLglY4IHRqOQmh6Ao6wkJYaJkarshKU8VUtId4=
|
||||||
github.com/changkun/lockfree v0.0.1/go.mod h1:3bKiaXn/iNzIPlSvSOMSVbRQUQtAp8qUAyBUtzU11s4=
|
github.com/changkun/lockfree v0.0.1/go.mod h1:3bKiaXn/iNzIPlSvSOMSVbRQUQtAp8qUAyBUtzU11s4=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@ -81,17 +87,28 @@ github.com/function61/gokit v0.0.0-20231117065306-355fe206d542 h1:a9BTN+DOboRkVi
|
|||||||
github.com/function61/gokit v0.0.0-20231117065306-355fe206d542/go.mod h1:sJY957+7ush4oj4ElOMhUFaFIriAFNAGYzVh2tFJNy0=
|
github.com/function61/gokit v0.0.0-20231117065306-355fe206d542/go.mod h1:sJY957+7ush4oj4ElOMhUFaFIriAFNAGYzVh2tFJNy0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
|
github.com/gin-contrib/secure v0.0.1 h1:DMMx3xXDY+MLA9kzIPHksyzC5/V5J6014c/WAmdS2gQ=
|
||||||
|
github.com/gin-contrib/secure v0.0.1/go.mod h1:6kseOBFrSR3Is/kM1jDhCg/WsXAMvKJkuPvG9dGph/c=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
|
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||||
|
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
|
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
|
||||||
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
@ -136,6 +153,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
@ -164,12 +182,18 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
|||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8 h1:avdze4CXO+1TsCV84EH7ueX5WOc0GDjDYCyQWlC51Lo=
|
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8 h1:avdze4CXO+1TsCV84EH7ueX5WOc0GDjDYCyQWlC51Lo=
|
||||||
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8/go.mod h1:D+xdhbGYvTi/6hHTULOhUiYwEM89FvmRfPKEms6MJsc=
|
github.com/jonstacks/iomerge v0.0.0-20200607001240-c9a527e8abe8/go.mod h1:D+xdhbGYvTi/6hHTULOhUiYwEM89FvmRfPKEms6MJsc=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@ -178,14 +202,24 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
@ -204,6 +238,10 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
|||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/rs/cors v1.8.1 h1:OrP+y5H+5Md29ACTA9imbALaKHwOSUZkcizaG0LT5ow=
|
||||||
|
github.com/rs/cors v1.8.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
|
github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644 h1:BBwREPixt0iE77C9z7DOenoeh5OGFrzyL1cWOp5oQTs=
|
||||||
|
github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644/go.mod h1:gmu40DuK3SLdKUzGOUofS3UDZwyeOUy6ZjPPuaALatw=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
||||||
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
||||||
@ -224,17 +262,25 @@ github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@ -253,6 +299,9 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
|||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||||
golang.design/x/lockfree v0.0.1 h1:IHFNwZgM5bnZYWkEbzn5lWHMYr8WsRBdCJ/RBVY0xMM=
|
golang.design/x/lockfree v0.0.1 h1:IHFNwZgM5bnZYWkEbzn5lWHMYr8WsRBdCJ/RBVY0xMM=
|
||||||
golang.design/x/lockfree v0.0.1/go.mod h1:iaZUx6UgZaOdePjzI6wFd+seYMl1i0rsG8+xKvA8c4I=
|
golang.design/x/lockfree v0.0.1/go.mod h1:iaZUx6UgZaOdePjzI6wFd+seYMl1i0rsG8+xKvA8c4I=
|
||||||
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
@ -363,6 +412,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -389,7 +439,9 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
@ -566,6 +618,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -582,5 +636,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
|||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package api
|
package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -6,13 +6,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/config"
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/logger"
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server"
|
"github.com/Neur0toxine/sshpoke/internal/server"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/convert"
|
"github.com/Neur0toxine/sshpoke/pkg/convert"
|
||||||
plugin2 "github.com/Neur0toxine/sshpoke/pkg/plugin"
|
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/plugin/pb"
|
"github.com/Neur0toxine/sshpoke/pkg/plugin/pb"
|
||||||
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
@ -22,6 +20,7 @@ var ErrUnauthorized = errors.New("unauthorized")
|
|||||||
|
|
||||||
type pluginAPI struct {
|
type pluginAPI struct {
|
||||||
pb.UnimplementedPluginServiceServer
|
pb.UnimplementedPluginServiceServer
|
||||||
|
log *zap.SugaredLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pluginAPI) Event(_ *emptypb.Empty, stream pb.PluginService_EventServer) error {
|
func (p *pluginAPI) Event(_ *emptypb.Empty, stream pb.PluginService_EventServer) error {
|
||||||
@ -29,13 +28,13 @@ func (p *pluginAPI) Event(_ *emptypb.Empty, stream pb.PluginService_EventServer)
|
|||||||
if pl == nil {
|
if pl == nil {
|
||||||
return ErrUnauthorized
|
return ErrUnauthorized
|
||||||
}
|
}
|
||||||
logger.Sugar.Debugw("attached plugin event stream", "serverName", pl.Name())
|
p.log.Debugw("attached plugin event stream", "serverName", pl.Name())
|
||||||
err := pl.Listen(stream.Context(), &Stream{stream: stream})
|
err := pl.Listen(stream.Context(), &Stream{stream: stream})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Sugar.Debugw("detached plugin event stream", "serverName", pl.Name(), "error", err)
|
p.log.Debugw("detached plugin event stream", "serverName", pl.Name(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Sugar.Debugw("detached plugin event stream", "serverName", pl.Name())
|
p.log.Debugw("detached plugin event stream", "serverName", pl.Name())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,20 +59,16 @@ func (p *pluginAPI) receiverForContext(ctx context.Context) plugin.Plugin {
|
|||||||
return server.DefaultManager.PluginByToken(tokens[0])
|
return server.DefaultManager.PluginByToken(tokens[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartPluginAPI() {
|
func StartServer(port int, log *zap.SugaredLogger) {
|
||||||
port := config.Default.API.Plugin.Port
|
|
||||||
if port == 0 {
|
|
||||||
port = plugin2.DefaultPort
|
|
||||||
}
|
|
||||||
socket, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
socket, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Sugar.Errorf("cannot start plugin API server on port %d: %s", port, err)
|
log.Errorf("cannot start plugin API server on port %d: %s", port, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
pb.RegisterPluginServiceServer(s, &pluginAPI{})
|
pb.RegisterPluginServiceServer(s, &pluginAPI{log: log})
|
||||||
logger.Sugar.Debugf("starting plugin server on :%d", port)
|
log.Debugf("starting plugin server on :%d", port)
|
||||||
if err := s.Serve(socket); err != nil {
|
if err := s.Serve(socket); err != nil {
|
||||||
logger.Sugar.Fatalf("cannot start plugin server on :%d: %s", port, err)
|
log.Fatalf("cannot start plugin server on :%d: %s", port, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package api
|
package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/convert"
|
"github.com/Neur0toxine/sshpoke/pkg/convert"
|
12
internal/api/web/handler/config.go
Normal file
12
internal/api/web/handler/config.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/config"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Config(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, config.Default)
|
||||||
|
}
|
12
internal/api/web/handler/status.go
Normal file
12
internal/api/web/handler/status.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/server"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Status(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, server.DefaultManager.StatusMap())
|
||||||
|
}
|
31
internal/api/web/middleware/auth.go
Normal file
31
internal/api/web/middleware/auth.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthHeader = "Authorization"
|
||||||
|
bearerPrefix = "Bearer "
|
||||||
|
)
|
||||||
|
|
||||||
|
func Auth(token string) gin.HandlerFunc {
|
||||||
|
if token == "" {
|
||||||
|
return func(c *gin.Context) {}
|
||||||
|
}
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
header := c.GetHeader(AuthHeader)
|
||||||
|
if strings.HasPrefix(header, bearerPrefix) {
|
||||||
|
header = header[len(bearerPrefix):]
|
||||||
|
}
|
||||||
|
|
||||||
|
if header != token {
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
38
internal/api/web/middleware/log.go
Normal file
38
internal/api/web/middleware/log.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/api/web/middleware/log"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetupLogger(zapLog *zap.SugaredLogger) gin.HandlerFunc {
|
||||||
|
gin.DefaultWriter = log.AsWriter(zapLog, zap.DebugLevel)
|
||||||
|
gin.DefaultErrorWriter = log.AsWriter(zapLog, zap.ErrorLevel)
|
||||||
|
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
|
||||||
|
zapLog.Debugw("route",
|
||||||
|
"method", httpMethod,
|
||||||
|
"path", absolutePath,
|
||||||
|
"handler", handlerName,
|
||||||
|
"handlerNum", nuHandlers)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
start := time.Now()
|
||||||
|
c.Next()
|
||||||
|
now := time.Now()
|
||||||
|
zapLog.Debugw(fmt.Sprintf("%d %s | %s %s",
|
||||||
|
c.Writer.Status(), http.StatusText(c.Writer.Status()), c.Request.Method, c.Request.URL.String()),
|
||||||
|
"ts", now,
|
||||||
|
"latency", now.Sub(start),
|
||||||
|
"clientIp", c.ClientIP(),
|
||||||
|
"method", c.Request.Method,
|
||||||
|
"status", c.Writer.Status(),
|
||||||
|
"error", c.Errors.ByType(gin.ErrorTypePrivate).String(),
|
||||||
|
"bodyLength", c.Writer.Size())
|
||||||
|
}
|
||||||
|
}
|
37
internal/api/web/middleware/log/adapter.go
Normal file
37
internal/api/web/middleware/log/adapter.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type writerLogger struct {
|
||||||
|
log *zap.SugaredLogger
|
||||||
|
level zapcore.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
func AsWriter(log *zap.SugaredLogger, level zapcore.Level) io.Writer {
|
||||||
|
return &writerLogger{log: log}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writerLogger) Write(p []byte) (n int, err error) {
|
||||||
|
switch w.level {
|
||||||
|
case zapcore.DebugLevel:
|
||||||
|
w.log.Debug(string(p))
|
||||||
|
case zapcore.InfoLevel:
|
||||||
|
w.log.Info(string(p))
|
||||||
|
case zapcore.WarnLevel:
|
||||||
|
w.log.Warn(string(p))
|
||||||
|
case zapcore.ErrorLevel:
|
||||||
|
w.log.Error(string(p))
|
||||||
|
case zapcore.DPanicLevel:
|
||||||
|
w.log.DPanic(string(p))
|
||||||
|
case zapcore.PanicLevel:
|
||||||
|
w.log.Panic(string(p))
|
||||||
|
case zapcore.FatalLevel:
|
||||||
|
w.log.Fatal(string(p))
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
57
internal/api/web/server.go
Normal file
57
internal/api/web/server.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/api/web/handler"
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/api/web/middleware"
|
||||||
|
"github.com/Neur0toxine/sshpoke/internal/logger"
|
||||||
|
"github.com/gin-contrib/secure"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
cors "github.com/rs/cors/wrapper/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultPort = 25680
|
||||||
|
httpProto = "http://"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartServer(token string, port int, log *zap.SugaredLogger, debug bool) {
|
||||||
|
if !debug {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
}
|
||||||
|
logMiddleware := middleware.SetupLogger(log)
|
||||||
|
g := gin.New()
|
||||||
|
g.Use(logMiddleware)
|
||||||
|
g.Use(cors.New(cors.Options{
|
||||||
|
AllowedOrigins: []string{
|
||||||
|
httpProto + net.JoinHostPort("localhost", strconv.Itoa(port)),
|
||||||
|
httpProto + net.JoinHostPort("127.0.0.1", strconv.Itoa(port)),
|
||||||
|
},
|
||||||
|
AllowedMethods: []string{"HEAD", "GET", "POST", "PUT", "DELETE"},
|
||||||
|
MaxAge: 60 * 10,
|
||||||
|
AllowCredentials: true,
|
||||||
|
}))
|
||||||
|
g.Use(secure.New(secureConfig()))
|
||||||
|
router(g, token)
|
||||||
|
err := g.Run(net.JoinHostPort("127.0.0.1", strconv.Itoa(port)))
|
||||||
|
if err != nil {
|
||||||
|
logger.Sugar.Errorf("cannot start Web API server on port %d: %s", port, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func router(g *gin.Engine, token string) {
|
||||||
|
api := g.Group("/api/v1")
|
||||||
|
{
|
||||||
|
api.Use(middleware.Auth(token))
|
||||||
|
api.GET("/config", handler.Config)
|
||||||
|
api.GET("/status", handler.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func secureConfig() secure.Config {
|
||||||
|
cfg := secure.DefaultConfig()
|
||||||
|
cfg.SSLRedirect = false
|
||||||
|
return cfg
|
||||||
|
}
|
@ -11,33 +11,33 @@ import (
|
|||||||
var Default Config
|
var Default Config
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Debug bool `mapstructure:"debug"`
|
Debug bool `mapstructure:"debug" json:"debug"`
|
||||||
API API `mapstructure:"api"`
|
API API `mapstructure:"api" json:"api"`
|
||||||
Docker DockerConfig `mapstructure:"docker"`
|
Docker DockerConfig `mapstructure:"docker" json:"docker"`
|
||||||
DefaultServer string `mapstructure:"default_server"`
|
DefaultServer string `mapstructure:"default_server" json:"default_server"`
|
||||||
Servers []Server `mapstructure:"servers"`
|
Servers []Server `mapstructure:"servers" json:"servers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
Web WebAPI `mapstructure:"web"`
|
Web WebAPI `mapstructure:"web" json:"web"`
|
||||||
Plugin PluginAPI `mapstructure:"plugin"`
|
Plugin PluginAPI `mapstructure:"plugin" json:"plugin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebAPI struct {
|
type WebAPI struct {
|
||||||
Port int `mapstructure:"port" validate:"gte=0,lte=65535"`
|
Port int `mapstructure:"port" json:"port" validate:"gte=0,lte=65535"`
|
||||||
Token string `mapstructure:"token"`
|
Token string `mapstructure:"token" json:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PluginAPI struct {
|
type PluginAPI struct {
|
||||||
Port int `mapstructure:"port" validate:"gte=0,lte=65535"`
|
Port int `mapstructure:"port" json:"port" validate:"gte=0,lte=65535"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DockerConfig struct {
|
type DockerConfig struct {
|
||||||
FromEnv *bool `mapstructure:"from_env,omitempty"`
|
FromEnv *bool `mapstructure:"from_env,omitempty" json:"from_env"`
|
||||||
CertPath string `mapstructure:"cert_path"`
|
CertPath string `mapstructure:"cert_path" json:"cert_path,omitempty"`
|
||||||
TLSVerify *bool `mapstructure:"tls_verify,omitempty"`
|
TLSVerify *bool `mapstructure:"tls_verify,omitempty" json:"tls_verify,omitempty"`
|
||||||
Host string `mapstructure:"host"`
|
Host string `mapstructure:"host" json:"host,omitempty"`
|
||||||
Version string `mapstructure:"version"`
|
Version string `mapstructure:"version" json:"version,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DriverParams map[string]interface{}
|
type DriverParams map[string]interface{}
|
||||||
@ -47,13 +47,13 @@ type DriverType string
|
|||||||
const (
|
const (
|
||||||
DriverSSH DriverType = "ssh"
|
DriverSSH DriverType = "ssh"
|
||||||
DriverPlugin DriverType = "plugin"
|
DriverPlugin DriverType = "plugin"
|
||||||
DriverNull DriverType = "null"
|
DriverNil DriverType = "nil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Name string `mapstructure:"name" validate:"required"`
|
Name string `mapstructure:"name" json:"name" validate:"required"`
|
||||||
Driver DriverType `mapstructure:"driver"`
|
Driver DriverType `mapstructure:"driver" json:"driver"`
|
||||||
Params DriverParams `mapstructure:"params"`
|
Params DriverParams `mapstructure:"params" json:"params,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DockerConfig) Opts(c *client.Client) error {
|
func (d DockerConfig) Opts(c *client.Client) error {
|
||||||
|
@ -50,10 +50,10 @@ func (d *Docker) Containers() map[string]dto.Container {
|
|||||||
return containers
|
return containers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Docker) GetContainer(id string) (dto.Container, bool) {
|
func (d *Docker) GetContainer(id string, all bool) (dto.Container, bool) {
|
||||||
container, err := d.cli.ContainerList(d.ctx, types.ContainerListOptions{
|
container, err := d.cli.ContainerList(d.ctx, types.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(filters.Arg("id", id)),
|
Filters: filters.NewArgs(filters.Arg("id", id)),
|
||||||
All: true,
|
All: all,
|
||||||
})
|
})
|
||||||
if err != nil || len(container) != 1 {
|
if err != nil || len(container) != 1 {
|
||||||
return dto.Container{}, false
|
return dto.Container{}, false
|
||||||
|
@ -3,6 +3,7 @@ package docker
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/logger"
|
"github.com/Neur0toxine/sshpoke/internal/logger"
|
||||||
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
||||||
@ -78,7 +79,7 @@ func dockerContainerToInternal(container types.Container) (result dto.Container,
|
|||||||
|
|
||||||
return dto.Container{
|
return dto.Container{
|
||||||
ID: container.ID,
|
ID: container.ID,
|
||||||
Names: container.Names,
|
Names: convertNames(container.Names),
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Port: uint16(port),
|
Port: uint16(port),
|
||||||
Server: labels.Server,
|
Server: labels.Server,
|
||||||
@ -86,6 +87,17 @@ func dockerContainerToInternal(container types.Container) (result dto.Container,
|
|||||||
}, true
|
}, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertNames(src []string) []string {
|
||||||
|
if len(src) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dst := make([]string, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = strings.TrimLeft(src[i], "/")
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
func getKeyVal(m map[string]*network.EndpointSettings) *network.EndpointSettings {
|
func getKeyVal(m map[string]*network.EndpointSettings) *network.EndpointSettings {
|
||||||
for _, v := range m {
|
for _, v := range m {
|
||||||
return v
|
return v
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/config"
|
"github.com/Neur0toxine/sshpoke/internal/config"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/base"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/base"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/null"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/nil"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/plugin"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/server/driver/ssh"
|
"github.com/Neur0toxine/sshpoke/internal/server/driver/ssh"
|
||||||
)
|
)
|
||||||
@ -16,9 +16,9 @@ func New(ctx context.Context, name string, driver config.DriverType, params conf
|
|||||||
return ssh.New(ctx, name, params)
|
return ssh.New(ctx, name, params)
|
||||||
case config.DriverPlugin:
|
case config.DriverPlugin:
|
||||||
return plugin.New(ctx, name, params)
|
return plugin.New(ctx, name, params)
|
||||||
case config.DriverNull:
|
case config.DriverNil:
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
return null.New(ctx, name, params)
|
return nil.New(ctx, name, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package null
|
package nil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -8,26 +8,26 @@ import (
|
|||||||
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
"github.com/Neur0toxine/sshpoke/pkg/dto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Null driver only logs container events to debug log. It is used when user provides invalid driver type.
|
// Nil driver only logs container events to debug log. It is used when user provides invalid driver type.
|
||||||
// You can use it directly, but it won't do anything, so... why bother?
|
// You can use it directly, but it won't do anything, so... why bother?
|
||||||
type Null struct {
|
type Nil struct {
|
||||||
base.Base
|
base.Base
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, name string, params config.DriverParams) (base.Driver, error) {
|
func New(ctx context.Context, name string, params config.DriverParams) (base.Driver, error) {
|
||||||
return &Null{
|
return &Nil{
|
||||||
Base: base.New(ctx, name),
|
Base: base.New(ctx, name),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Null) Handle(event dto.Event) error {
|
func (d *Nil) Handle(event dto.Event) error {
|
||||||
d.Log().Debugw("handling event with null driver", "serverName", d.Name(), "event", event)
|
d.Log().Debugw("handling event with nil driver", "serverName", d.Name(), "event", event)
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
case dto.EventStart:
|
case dto.EventStart:
|
||||||
d.PushEventStatus(dto.EventStatus{
|
d.PushEventStatus(dto.EventStatus{
|
||||||
Type: dto.EventStart,
|
Type: dto.EventStart,
|
||||||
ID: event.Container.ID,
|
ID: event.Container.ID,
|
||||||
Domain: "https://" + event.Container.ID + "null.dev",
|
Domain: "https://" + event.Container.ID + ".nil.dev",
|
||||||
})
|
})
|
||||||
case dto.EventStop, dto.EventShutdown:
|
case dto.EventStop, dto.EventShutdown:
|
||||||
d.PushEventStatus(dto.EventStatus{
|
d.PushEventStatus(dto.EventStatus{
|
||||||
@ -38,8 +38,8 @@ func (d *Null) Handle(event dto.Event) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Null) Driver() config.DriverType {
|
func (d *Nil) Driver() config.DriverType {
|
||||||
return config.DriverNull
|
return config.DriverNil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Null) WaitForShutdown() {}
|
func (d *Nil) WaitForShutdown() {}
|
@ -3,7 +3,9 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Neur0toxine/sshpoke/internal/config"
|
"github.com/Neur0toxine/sshpoke/internal/config"
|
||||||
"github.com/Neur0toxine/sshpoke/internal/docker"
|
"github.com/Neur0toxine/sshpoke/internal/docker"
|
||||||
@ -16,14 +18,17 @@ import (
|
|||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
rw sync.RWMutex
|
rw sync.RWMutex
|
||||||
|
forwardsLock sync.Mutex
|
||||||
servers map[string]base.Driver
|
servers map[string]base.Driver
|
||||||
plugins map[string]plugin.Plugin
|
plugins map[string]plugin.Plugin
|
||||||
statusMap map[string]serverStatus
|
statusMap map[string]ServerStatus
|
||||||
|
forwards map[string]bool
|
||||||
statusLock sync.RWMutex
|
statusLock sync.RWMutex
|
||||||
|
ctx context.Context
|
||||||
defaultServer string
|
defaultServer string
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverStatus struct {
|
type ServerStatus struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Connections Connections `json:"connections"`
|
Connections Connections `json:"connections"`
|
||||||
}
|
}
|
||||||
@ -36,8 +41,11 @@ var (
|
|||||||
|
|
||||||
func NewManager(ctx context.Context, servers []config.Server, defaultServer string) *Manager {
|
func NewManager(ctx context.Context, servers []config.Server, defaultServer string) *Manager {
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
|
ctx: ctx,
|
||||||
servers: make(map[string]base.Driver),
|
servers: make(map[string]base.Driver),
|
||||||
plugins: make(map[string]plugin.Plugin),
|
plugins: make(map[string]plugin.Plugin),
|
||||||
|
statusMap: make(map[string]ServerStatus),
|
||||||
|
forwards: make(map[string]bool),
|
||||||
defaultServer: defaultServer,
|
defaultServer: defaultServer,
|
||||||
}
|
}
|
||||||
for _, serverConfig := range servers {
|
for _, serverConfig := range servers {
|
||||||
@ -61,7 +69,9 @@ func NewManager(ctx context.Context, servers []config.Server, defaultServer stri
|
|||||||
m.plugins[pl.Token()] = pl
|
m.plugins[pl.Token()] = pl
|
||||||
}
|
}
|
||||||
m.servers[serverConfig.Name] = server
|
m.servers[serverConfig.Name] = server
|
||||||
|
m.statusMap[serverConfig.Name] = ServerStatus{Name: serverConfig.Name, Connections: make(Connections)}
|
||||||
}
|
}
|
||||||
|
go m.runMarkAndSweepForwards()
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +89,22 @@ func (m *Manager) ProcessEvent(event dto.Event) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return ErrNoSuchServer
|
return ErrNoSuchServer
|
||||||
}
|
}
|
||||||
return srv.Handle(event)
|
if err := srv.Handle(event); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer m.forwardsLock.Unlock()
|
||||||
|
m.forwardsLock.Lock()
|
||||||
|
switch event.Type {
|
||||||
|
case dto.EventStart:
|
||||||
|
m.forwards[m.forwardID(serverName, event.Container.ID)] = false
|
||||||
|
case dto.EventStop, dto.EventError, dto.EventShutdown:
|
||||||
|
delete(m.forwards, m.forwardID(serverName, event.Container.ID))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) forwardID(serverName, containerID string) string {
|
||||||
|
return serverName + ":" + containerID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) eventStatusCallback(serverName string) base.EventStatusCallback {
|
func (m *Manager) eventStatusCallback(serverName string) base.EventStatusCallback {
|
||||||
@ -91,28 +116,74 @@ func (m *Manager) eventStatusCallback(serverName string) base.EventStatusCallbac
|
|||||||
func (m *Manager) processEventStatus(serverName string, event dto.EventStatus) {
|
func (m *Manager) processEventStatus(serverName string, event dto.EventStatus) {
|
||||||
logger.Sugar.Debugw("received EventStatus from server",
|
logger.Sugar.Debugw("received EventStatus from server",
|
||||||
"serverName", serverName, "eventStatus", event)
|
"serverName", serverName, "eventStatus", event)
|
||||||
m.statusLock.RLock()
|
item, found := docker.Default.GetContainer(event.ID, true)
|
||||||
_, exists := m.statusMap[serverName]
|
|
||||||
if !exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.statusLock.RUnlock()
|
|
||||||
defer m.statusLock.Unlock()
|
|
||||||
m.statusLock.Lock()
|
|
||||||
item, found := docker.Default.GetContainer(event.ID)
|
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer m.forwardsLock.Unlock()
|
||||||
|
m.forwardsLock.Lock()
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
case dto.EventStart:
|
case dto.EventStart:
|
||||||
|
defer m.statusLock.Unlock()
|
||||||
|
m.statusLock.Lock()
|
||||||
item.Domain = event.Domain
|
item.Domain = event.Domain
|
||||||
|
m.forwards[m.forwardID(serverName, item.ID)] = false
|
||||||
|
m.statusMap[serverName].Connections[item.ID] = item
|
||||||
case dto.EventStop, dto.EventShutdown, dto.EventError:
|
case dto.EventStop, dto.EventShutdown, dto.EventError:
|
||||||
|
defer m.statusLock.Unlock()
|
||||||
|
m.statusLock.Lock()
|
||||||
item.Domain = ""
|
item.Domain = ""
|
||||||
|
delete(m.forwards, m.forwardID(serverName, item.ID))
|
||||||
|
delete(m.statusMap[serverName].Connections, item.ID)
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.statusMap[serverName].Connections[item.ID] = item
|
}
|
||||||
|
|
||||||
|
func (m *Manager) StatusMap() map[string]ServerStatus {
|
||||||
|
defer m.statusLock.RUnlock()
|
||||||
|
m.statusLock.RLock()
|
||||||
|
return m.statusMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// runMarkAndSweepForwards runs mark-and-sweep on the started forwards every 10 seconds.
|
||||||
|
// This job is necessary because Docker sometimes forgets to notify us that containers
|
||||||
|
// were stopped (usually happens when spamming Ctrl+C after `docker compose run`).
|
||||||
|
func (m *Manager) runMarkAndSweepForwards() {
|
||||||
|
ticker := time.NewTicker(time.Second * 10)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-m.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
m.markAndSweepForwards()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// markAndSweepForwards marks stopped containers for removal on the first run and removes them from forwards later.
|
||||||
|
// This job will remove containers from forwards if Docker didn't notify us about stopping containers for some reason.
|
||||||
|
func (m *Manager) markAndSweepForwards() {
|
||||||
|
defer m.forwardsLock.Unlock()
|
||||||
|
m.forwardsLock.Lock()
|
||||||
|
|
||||||
|
for id, state := range m.forwards {
|
||||||
|
forwardIDs := strings.Split(id, ":")
|
||||||
|
serverName, containerID := forwardIDs[0], forwardIDs[1]
|
||||||
|
_, found := docker.Default.GetContainer(containerID, false)
|
||||||
|
if found {
|
||||||
|
m.forwards[id] = false // unmark
|
||||||
|
} else {
|
||||||
|
if state {
|
||||||
|
m.processEventStatus(serverName, dto.EventStatus{
|
||||||
|
Type: dto.EventStop,
|
||||||
|
ID: containerID,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m.forwards[id] = true // mark
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) PluginByToken(token string) plugin.Plugin {
|
func (m *Manager) PluginByToken(token string) plugin.Plugin {
|
||||||
|
@ -57,6 +57,6 @@ type Container struct {
|
|||||||
IP net.IP `json:"ip"`
|
IP net.IP `json:"ip"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
Server string `json:"-"`
|
Server string `json:"-"`
|
||||||
RemoteHost string `json:"remote_host"`
|
RemoteHost string `json:"remote_host,omitempty"`
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user