Merge branch 'main' of github.com:OliveTin/OliveTin
This commit is contained in:
commit
3ea14f1353
|
|
@ -0,0 +1,44 @@
|
||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = []
|
||||||
|
bin = "./OliveTin"
|
||||||
|
cmd = "go build -o OliveTin github.com/OliveTin/OliveTin/cmd/OliveTin"
|
||||||
|
delay = 1
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = true
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
||||||
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '>=1.18.0'
|
go-version: '^1.18.0'
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: grpc
|
- name: grpc
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ jobs:
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '^1.16.0'
|
go-version: '^1.18.0'
|
||||||
|
cache: true
|
||||||
|
|
||||||
- name: deps
|
- name: deps
|
||||||
run: make grpc
|
run: make grpc
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ reports
|
||||||
releases/
|
releases/
|
||||||
dist/
|
dist/
|
||||||
installation-id.txt
|
installation-id.txt
|
||||||
|
tmp/
|
||||||
|
|
|
||||||
|
|
@ -236,4 +236,3 @@ release:
|
||||||
- [Ask for help and chat with others users in the Discord community](https://discord.gg/jhYWWpNJ3v)
|
- [Ask for help and chat with others users in the Discord community](https://discord.gg/jhYWWpNJ3v)
|
||||||
|
|
||||||
Thanks for your interest in OliveTin!
|
Thanks for your interest in OliveTin!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v3.2.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-added-large-files
|
||||||
|
|
@ -8,16 +8,16 @@ message Action {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
string title = 2;
|
string title = 2;
|
||||||
string icon = 3;
|
string icon = 3;
|
||||||
bool canExec = 4;
|
bool can_exec = 4;
|
||||||
|
|
||||||
repeated ActionArgument arguments = 5;
|
repeated ActionArgument arguments = 5;
|
||||||
|
bool popup_on_start = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ActionArgument {
|
message ActionArgument {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string title = 2;
|
string title = 2;
|
||||||
string type = 3;
|
string type = 3;
|
||||||
string defaultValue = 4;
|
string default_value = 4;
|
||||||
|
|
||||||
repeated ActionArgumentChoice choices = 5;
|
repeated ActionArgumentChoice choices = 5;
|
||||||
|
|
||||||
|
|
@ -44,9 +44,11 @@ message GetDashboardComponentsResponse {
|
||||||
message GetDashboardComponentsRequest {}
|
message GetDashboardComponentsRequest {}
|
||||||
|
|
||||||
message StartActionRequest {
|
message StartActionRequest {
|
||||||
string actionName = 1;
|
string action_name = 1;
|
||||||
|
|
||||||
repeated StartActionArgument arguments = 2;
|
repeated StartActionArgument arguments = 2;
|
||||||
|
|
||||||
|
string uuid = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StartActionArgument {
|
message StartActionArgument {
|
||||||
|
|
@ -55,22 +57,28 @@ message StartActionArgument {
|
||||||
}
|
}
|
||||||
|
|
||||||
message StartActionResponse {
|
message StartActionResponse {
|
||||||
LogEntry logEntry = 1;
|
string execution_uuid = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetLogsRequest{};
|
message GetLogsRequest{};
|
||||||
|
|
||||||
message LogEntry {
|
message LogEntry {
|
||||||
string datetime = 1;
|
string datetime_started = 1;
|
||||||
string actionTitle = 2;
|
string action_title = 2;
|
||||||
string stdout = 3;
|
string stdout = 3;
|
||||||
string stderr = 4;
|
string stderr = 4;
|
||||||
bool timedOut = 5;
|
bool timed_out = 5;
|
||||||
int32 exitCode = 6;
|
int32 exit_code = 6;
|
||||||
string user = 7;
|
string user = 7;
|
||||||
string userClass = 8;
|
string user_class = 8;
|
||||||
string actionIcon = 9;
|
string action_icon = 9;
|
||||||
repeated string tags = 10;
|
repeated string tags = 10;
|
||||||
|
string execution_uuid = 11;
|
||||||
|
string datetime_finished = 12;
|
||||||
|
string uuid = 13;
|
||||||
|
bool execution_started = 14;
|
||||||
|
bool execution_finished = 15;
|
||||||
|
bool blocked = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetLogsResponse {
|
message GetLogsResponse {
|
||||||
|
|
@ -87,10 +95,26 @@ message ValidateArgumentTypeResponse {
|
||||||
string description = 2;
|
string description = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message WatchExecutionRequest {
|
||||||
|
string execution_uuid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WatchExecutionUpdate {
|
||||||
|
string update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExecutionStatusRequest {
|
||||||
|
string execution_uuid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExecutionStatusResponse {
|
||||||
|
LogEntry log_entry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message WhoAmIRequest {}
|
message WhoAmIRequest {}
|
||||||
|
|
||||||
message WhoAmIResponse {
|
message WhoAmIResponse {
|
||||||
string authenticatedUser = 1;
|
string authenticated_user = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SosReportRequest {}
|
message SosReportRequest {}
|
||||||
|
|
@ -99,7 +123,7 @@ message SosReportResponse {
|
||||||
string alert = 1;
|
string alert = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
service OliveTinApi {
|
service OliveTinApiService {
|
||||||
rpc GetDashboardComponents(GetDashboardComponentsRequest) returns (GetDashboardComponentsResponse) {
|
rpc GetDashboardComponents(GetDashboardComponentsRequest) returns (GetDashboardComponentsResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
get: "/api/GetDashboardComponents"
|
get: "/api/GetDashboardComponents"
|
||||||
|
|
@ -113,6 +137,13 @@ service OliveTinApi {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc ExecutionStatus(ExecutionStatusRequest) returns (ExecutionStatusResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/api/ExecutionStatus"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
rpc GetLogs(GetLogsRequest) returns (GetLogsResponse) {
|
rpc GetLogs(GetLogsRequest) returns (GetLogsResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
get: "/api/GetLogs"
|
get: "/api/GetLogs"
|
||||||
|
|
|
||||||
|
|
@ -111,4 +111,3 @@ actions:
|
||||||
```
|
```
|
||||||
|
|
||||||
A full example config can be found at in this repository - [config.yaml](https://github.com/OliveTin/OliveTin/blob/main/config.yaml).
|
A full example config can be found at in this repository - [config.yaml](https://github.com/OliveTin/OliveTin/blob/main/config.yaml).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,3 @@ plugins:
|
||||||
|
|
||||||
# - name: openapiv2
|
# - name: openapiv2
|
||||||
# out: reports/openapiv2
|
# out: reports/openapiv2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/OliveTin/OliveTin/internal/oncron"
|
"github.com/OliveTin/OliveTin/internal/oncron"
|
||||||
"github.com/OliveTin/OliveTin/internal/onstartup"
|
"github.com/OliveTin/OliveTin/internal/onstartup"
|
||||||
updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
|
updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
|
||||||
|
"github.com/OliveTin/OliveTin/internal/websocket"
|
||||||
|
|
||||||
"github.com/OliveTin/OliveTin/internal/httpservers"
|
"github.com/OliveTin/OliveTin/internal/httpservers"
|
||||||
|
|
||||||
|
|
@ -110,6 +111,7 @@ func main() {
|
||||||
log.Debugf("Config: %+v", cfg)
|
log.Debugf("Config: %+v", cfg)
|
||||||
|
|
||||||
executor := executor.DefaultExecutor()
|
executor := executor.DefaultExecutor()
|
||||||
|
executor.AddListener(websocket.ExecutionListener)
|
||||||
|
|
||||||
go onstartup.Execute(cfg, executor)
|
go onstartup.Execute(cfg, executor)
|
||||||
go oncron.Schedule(cfg, executor)
|
go oncron.Schedule(cfg, executor)
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,18 @@ actions:
|
||||||
# This will run a simple script that you create.
|
# This will run a simple script that you create.
|
||||||
- title: Run backup script
|
- title: Run backup script
|
||||||
shell: /opt/backupScript.sh
|
shell: /opt/backupScript.sh
|
||||||
|
maxConcurrent: 1
|
||||||
icon: backup
|
icon: backup
|
||||||
|
|
||||||
|
- title: date
|
||||||
|
shell: date
|
||||||
|
|
||||||
# This will send 1 ping (-c 1)
|
# This will send 1 ping (-c 1)
|
||||||
# Docs: https://docs.olivetin.app/action-ping.html
|
# Docs: https://docs.olivetin.app/action-ping.html
|
||||||
- title: Ping host
|
- title: Ping host
|
||||||
shell: ping {{ host }} -c {{ count }}
|
shell: ping {{ host }} -c {{ count }}
|
||||||
icon: ping
|
icon: ping
|
||||||
|
timeout: 100
|
||||||
arguments:
|
arguments:
|
||||||
- name: host
|
- name: host
|
||||||
title: host
|
title: host
|
||||||
|
|
@ -76,4 +81,3 @@ actions:
|
||||||
shell: sleep 5
|
shell: sleep 5
|
||||||
timeout: 5
|
timeout: 5
|
||||||
icon: "😪"
|
icon: "😪"
|
||||||
|
|
||||||
|
|
|
||||||
93
go.mod
93
go.mod
|
|
@ -3,41 +3,45 @@ module github.com/OliveTin/OliveTin
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bufbuild/buf v1.15.1
|
github.com/bufbuild/buf v1.26.0
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/fzipp/gocyclo v0.6.0
|
github.com/fzipp/gocyclo v0.6.0
|
||||||
github.com/go-critic/go-critic v0.7.0
|
github.com/go-critic/go-critic v0.8.2
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
|
github.com/gorilla/websocket v1.4.1
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/viper v1.15.0
|
github.com/spf13/viper v1.15.0
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.4
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833
|
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
|
||||||
google.golang.org/grpc v1.53.0
|
google.golang.org/genproto/googleapis/api v0.0.0-20230807174057-1744710a1577
|
||||||
|
google.golang.org/grpc v1.57.0
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.31.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
github.com/bufbuild/connect-go v1.5.2 // indirect
|
github.com/bufbuild/connect-go v1.10.0 // indirect
|
||||||
github.com/bufbuild/protocompile v0.5.1 // indirect
|
github.com/bufbuild/connect-opentelemetry-go v0.4.0 // indirect
|
||||||
|
github.com/bufbuild/protocompile v0.6.0 // indirect
|
||||||
|
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
github.com/cristalhq/acmd v0.11.1 // indirect
|
github.com/cristalhq/acmd v0.11.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
github.com/docker/cli v24.0.5+incompatible // indirect
|
||||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||||
github.com/docker/docker v23.0.3+incompatible // indirect
|
github.com/docker/docker v24.0.5+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/felixge/fgprof v0.9.3 // indirect
|
github.com/felixge/fgprof v0.9.3 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.0.8 // indirect
|
github.com/go-chi/chi/v5 v5.0.10 // indirect
|
||||||
github.com/go-logr/logr v1.2.3 // indirect
|
github.com/go-logr/logr v1.2.4 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-toolsmith/astcast v1.1.0 // indirect
|
github.com/go-toolsmith/astcast v1.1.0 // indirect
|
||||||
github.com/go-toolsmith/astcopy v1.1.0 // indirect
|
github.com/go-toolsmith/astcopy v1.1.0 // indirect
|
||||||
|
|
@ -47,25 +51,24 @@ require (
|
||||||
github.com/go-toolsmith/pkgload v1.2.2 // indirect
|
github.com/go-toolsmith/pkgload v1.2.2 // indirect
|
||||||
github.com/go-toolsmith/strparse v1.1.0 // indirect
|
github.com/go-toolsmith/strparse v1.1.0 // indirect
|
||||||
github.com/go-toolsmith/typep v1.1.0 // indirect
|
github.com/go-toolsmith/typep v1.1.0 // indirect
|
||||||
github.com/gofrs/flock v0.8.1 // indirect
|
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/glog v1.0.0 // indirect
|
github.com/golang/glog v1.1.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/go-containerregistry v0.13.0 // indirect
|
github.com/google/go-containerregistry v0.16.1 // indirect
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect
|
github.com/google/pprof v0.0.0-20230808223545-4887780b67fb // 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/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect
|
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect
|
||||||
github.com/klauspost/compress v1.16.0 // indirect
|
github.com/klauspost/compress v1.16.7 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
github.com/moby/term v0.5.0 // 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.1.0-rc2 // indirect
|
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
|
@ -75,29 +78,33 @@ require (
|
||||||
github.com/quasilyte/gogrep v0.5.0 // indirect
|
github.com/quasilyte/gogrep v0.5.0 // indirect
|
||||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
||||||
github.com/rs/cors v1.8.3 // indirect
|
github.com/rs/cors v1.9.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/spf13/afero v1.9.3 // indirect
|
github.com/spf13/afero v1.9.3 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/cobra v1.6.1 // indirect
|
github.com/spf13/cobra v1.7.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
github.com/tetratelabs/wazero v1.4.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
|
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
go.opentelemetry.io/otel v1.16.0 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.opentelemetry.io/otel/metric v1.16.0 // indirect
|
||||||
go.uber.org/multierr v1.10.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
|
||||||
go.uber.org/zap v1.24.0 // indirect
|
go.opentelemetry.io/otel/trace v1.16.0 // indirect
|
||||||
golang.org/x/crypto v0.7.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
go.uber.org/zap v1.25.0 // indirect
|
||||||
golang.org/x/net v0.8.0 // indirect
|
golang.org/x/crypto v0.12.0 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/exp/typeparams v0.0.0-20230809150735-7b3493d9a819 // indirect
|
||||||
golang.org/x/sys v0.6.0 // indirect
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/term v0.6.0 // indirect
|
golang.org/x/net v0.14.0 // indirect
|
||||||
golang.org/x/text v0.8.0 // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.7.0 // indirect
|
golang.org/x/sys v0.11.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect
|
golang.org/x/term v0.11.0 // indirect
|
||||||
|
golang.org/x/text v0.12.0 // indirect
|
||||||
|
golang.org/x/tools v0.12.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20230807174057-1744710a1577 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
193
go.sum
193
go.sum
|
|
@ -40,15 +40,17 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
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.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||||
github.com/bufbuild/buf v1.15.1 h1:v7sK2uMEsGX4Z2hvu+xiMheH3C3AKBGfxPBgdUZYDQ8=
|
github.com/bufbuild/buf v1.26.0 h1:rB8pErEkxdUNhVZ3+ClFEoJRaa+o2FjEecCWL2S3Qs4=
|
||||||
github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE=
|
github.com/bufbuild/buf v1.26.0/go.mod h1:UMPncXMWgrmIM+0QpwTEwjNr2SA0z2YIVZZsmNflvB4=
|
||||||
github.com/bufbuild/connect-go v1.5.2 h1:G4EZd5gF1U1ZhhbVJXplbuUnfKpBZ5j5izqIwu2g2W8=
|
github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg=
|
||||||
github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk=
|
github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8=
|
||||||
github.com/bufbuild/protocompile v0.5.1 h1:mixz5lJX4Hiz4FpqFREJHIXLfaLBntfaJv1h+/jS+Qg=
|
github.com/bufbuild/connect-opentelemetry-go v0.4.0 h1:6JAn10SNqlQ/URhvRNGrIlczKw1wEXknBUUtmWqOiak=
|
||||||
github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40=
|
github.com/bufbuild/connect-opentelemetry-go v0.4.0/go.mod h1:nwPXYoDOoc2DGyKE/6pT1Q9MPSi2Et2e6BieMD0l6WU=
|
||||||
|
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
|
||||||
|
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
|
||||||
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/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=
|
||||||
|
|
@ -57,7 +59,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0=
|
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||||
|
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
|
|
@ -66,14 +69,14 @@ github.com/cristalhq/acmd v0.11.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgB
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy13Ul2Q5oM=
|
github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc=
|
||||||
github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho=
|
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
|
||||||
github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
|
@ -91,16 +94,16 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
|
||||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
||||||
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
||||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ=
|
github.com/go-critic/go-critic v0.8.2 h1:mekhZ9jw5NBEj3I8o/EywXw5zBfGAJuMo4VVVjtxF80=
|
||||||
github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64=
|
github.com/go-critic/go-critic v0.8.2/go.mod h1:nZPlrtVfOuLOe8GpvWTfcMzfkG0QVZWAziAeXpivfQo=
|
||||||
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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
|
github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
|
||||||
|
|
@ -122,7 +125,6 @@ github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJ
|
||||||
github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
|
github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
|
||||||
github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
|
github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
|
||||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
|
@ -130,8 +132,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
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=
|
||||||
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
|
@ -173,8 +175,8 @@ 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.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=
|
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
|
||||||
github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo=
|
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||||
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=
|
||||||
|
|
@ -189,8 +191,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso=
|
github.com/google/pprof v0.0.0-20230808223545-4887780b67fb h1:oqpb3Cwpc7EOml5PVGMYbSGmwNui2R7i8IW83gs4W0c=
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
github.com/google/pprof v0.0.0-20230808223545-4887780b67fb/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
|
@ -198,8 +200,10 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE=
|
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2/go.mod h1:7pdNwVWBBHGiCxa9lAszqCJMbfTISJ7oMftp8+UGV08=
|
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 h1:dygLcbEBA+t/P7ck6a8AkXv6juQ4cK0RHBoh32jxhHM=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2/go.mod h1:Ap9RLCIJVtgQg1/BBgVEfypOAySvvlcpcVQkSzJCH4Y=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
|
|
@ -207,7 +211,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 h1:2uT3aivO7NVpUPGcQX7RbHijHMyWix/yCnIrCWc+5co=
|
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 h1:2uT3aivO7NVpUPGcQX7RbHijHMyWix/yCnIrCWc+5co=
|
||||||
|
|
@ -217,10 +220,10 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
||||||
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/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/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
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=
|
||||||
|
|
@ -233,15 +236,15 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
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.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||||
|
|
@ -266,18 +269,18 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
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.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||||
github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
|
github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
|
||||||
github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
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/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
||||||
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
|
@ -294,11 +297,14 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
|
github.com/tetratelabs/wazero v1.4.0 h1:9/MirYvmkJ/zSUOygKY/ia3t+e+RqIZXKbylIby1WYk=
|
||||||
|
github.com/tetratelabs/wazero v1.4.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
||||||
|
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
|
||||||
|
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
|
||||||
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=
|
||||||
|
|
@ -309,19 +315,22 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
|
||||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
|
||||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
|
||||||
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
|
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
|
||||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
|
||||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
|
||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
|
||||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
|
||||||
|
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
|
||||||
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=
|
||||||
|
|
@ -329,8 +338,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
|
@ -341,12 +350,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s=
|
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb h1:WGs/bGIWYyAY5PVgGGMXqGGCxSJz4fpoUExb/vgqNCU=
|
golang.org/x/exp/typeparams v0.0.0-20230809150735-7b3493d9a819 h1:qdPQGUfaPzFgEbhQCulaXk+s0ETcox/vQd+f9YCIuxY=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20230809150735-7b3493d9a819/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
|
@ -370,8 +379,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
|
@ -403,8 +412,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
|
@ -424,8 +433,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -465,19 +474,19 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.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=
|
||||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
@ -531,8 +540,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
@ -599,8 +608,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
|
||||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds=
|
google.golang.org/genproto v0.0.0-20230807174057-1744710a1577 h1:Tyk/35yqszRCvaragTn5NnkY6IiKk/XvHzEWepo71N0=
|
||||||
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
|
google.golang.org/genproto v0.0.0-20230807174057-1744710a1577/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230807174057-1744710a1577 h1:xv8KoglAClYGkprUSmDTKaILtzfD8XzG9NYVXMprjKo=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230807174057-1744710a1577/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
|
@ -617,8 +630,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
|
||||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
|
@ -633,8 +646,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,3 @@ actions:
|
||||||
- title: Restart Plex
|
- title: Restart Plex
|
||||||
icon: smile
|
icon: smile
|
||||||
shell: docker restart plex
|
shell: docker restart plex
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,3 @@ describe('Homepage rendering', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,3 @@ describe('Hidden Footer', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,3 @@ describe('Hidden Nav', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,3 @@
|
||||||
//
|
//
|
||||||
// -- This will overwrite an existing command --
|
// -- This will overwrite an existing command --
|
||||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,3 @@ cp -f ./configs/config.$1.yaml ./configs/config.yaml
|
||||||
docker start olivetin
|
docker start olivetin
|
||||||
NO_COLOR=1 ./node_modules/.bin/cypress run --headless -s cypress/integration/$1/* || true
|
NO_COLOR=1 ./node_modules/.bin/cypress run --headless -s cypress/integration/$1/* || true
|
||||||
docker kill olivetin
|
docker kill olivetin
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -75,7 +75,10 @@ func getMetdataKeyOrEmpty(md metadata.MD, key string) string {
|
||||||
func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser {
|
func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser {
|
||||||
md, ok := metadata.FromIncomingContext(ctx)
|
md, ok := metadata.FromIncomingContext(ctx)
|
||||||
|
|
||||||
ret := &AuthenticatedUser{}
|
ret := &AuthenticatedUser{
|
||||||
|
Username: "guest",
|
||||||
|
Usergroup: "guest",
|
||||||
|
}
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
ret.Username = getMetdataKeyOrEmpty(md, "username")
|
ret.Username = getMetdataKeyOrEmpty(md, "username")
|
||||||
|
|
@ -87,7 +90,7 @@ func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"username": ret.Username,
|
"username": ret.Username,
|
||||||
"usergroup": ret.Usergroup,
|
"usergroup": ret.Usergroup,
|
||||||
}).Infof("UserFromContext")
|
}).Debugf("UserFromContext")
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ type Action struct {
|
||||||
Acls []string
|
Acls []string
|
||||||
ExecOnStartup bool
|
ExecOnStartup bool
|
||||||
ExecOnCron []string
|
ExecOnCron []string
|
||||||
|
MaxConcurrent int
|
||||||
Arguments []ActionArgument
|
Arguments []ActionArgument
|
||||||
|
PopupOnStart bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActionArgument objects appear on Actions.
|
// ActionArgument objects appear on Actions.
|
||||||
|
|
@ -73,9 +75,10 @@ type Config struct {
|
||||||
ShowNavigation bool
|
ShowNavigation bool
|
||||||
ShowNewVersions bool
|
ShowNewVersions bool
|
||||||
AuthJwtCookieName string
|
AuthJwtCookieName string
|
||||||
AuthJwtSecret string
|
AuthJwtSecret string // mutually exclusive with pub key config fields
|
||||||
AuthJwtClaimUsername string
|
AuthJwtClaimUsername string
|
||||||
AuthJwtClaimUserGroup string
|
AuthJwtClaimUserGroup string
|
||||||
|
AuthJwtPubKeyPath string // will read pub key from file on disk
|
||||||
AuthHttpHeaderUsername string
|
AuthHttpHeaderUsername string
|
||||||
AuthHttpHeaderUserGroup string
|
AuthHttpHeaderUserGroup string
|
||||||
DefaultPermissions PermissionsList
|
DefaultPermissions PermissionsList
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ func (action *Action) sanitize() {
|
||||||
|
|
||||||
action.Icon = lookupHTMLIcon(action.Icon)
|
action.Icon = lookupHTMLIcon(action.Icon)
|
||||||
|
|
||||||
|
if action.MaxConcurrent < 1 {
|
||||||
|
action.MaxConcurrent = 1
|
||||||
|
}
|
||||||
|
|
||||||
for idx := range action.Arguments {
|
for idx := range action.Arguments {
|
||||||
action.Arguments[idx].sanitize()
|
action.Arguments[idx].sanitize()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,9 @@ var (
|
||||||
|
|
||||||
func parseActionArguments(rawShellCommand string, values map[string]string, action *config.Action) (string, error) {
|
func parseActionArguments(rawShellCommand string, values map[string]string, action *config.Action) (string, error) {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"cmd": rawShellCommand,
|
"actionTitle": action.Title,
|
||||||
}).Infof("Before Parse Args")
|
"cmd": rawShellCommand,
|
||||||
|
}).Infof("Action parse args - Before")
|
||||||
|
|
||||||
r := regexp.MustCompile("{{ *?([a-zA-Z0-9_]+?) *?}}")
|
r := regexp.MustCompile("{{ *?([a-zA-Z0-9_]+?) *?}}")
|
||||||
matches := r.FindAllStringSubmatch(rawShellCommand, -1)
|
matches := r.FindAllStringSubmatch(rawShellCommand, -1)
|
||||||
|
|
@ -51,8 +52,9 @@ func parseActionArguments(rawShellCommand string, values map[string]string, acti
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"cmd": rawShellCommand,
|
"actionTitle": action.Title,
|
||||||
}).Infof("After Parse Args")
|
"cmd": rawShellCommand,
|
||||||
|
}).Infof("Action parse args - After")
|
||||||
|
|
||||||
return rawShellCommand, nil
|
return rawShellCommand, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,91 +8,77 @@ import (
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Executor represents a helper class for executing commands. It's main method
|
||||||
|
// is ExecRequest
|
||||||
|
type Executor struct {
|
||||||
|
Logs map[string]*InternalLogEntry
|
||||||
|
|
||||||
|
listeners []listener
|
||||||
|
|
||||||
|
chainOfCommand []executorStepFunc
|
||||||
|
}
|
||||||
|
|
||||||
// ExecutionRequest is a request to execute an action. It's passed to an
|
// ExecutionRequest is a request to execute an action. It's passed to an
|
||||||
// Executor. They're created from the grpcapi.
|
// Executor. They're created from the grpcapi.
|
||||||
type ExecutionRequest struct {
|
type ExecutionRequest struct {
|
||||||
ActionName string
|
ActionName string
|
||||||
Arguments map[string]string
|
Arguments map[string]string
|
||||||
|
UUID string
|
||||||
Tags []string
|
Tags []string
|
||||||
action *config.Action
|
action *config.Action
|
||||||
Cfg *config.Config
|
Cfg *config.Config
|
||||||
AuthenticatedUser *acl.AuthenticatedUser
|
AuthenticatedUser *acl.AuthenticatedUser
|
||||||
logEntry *InternalLogEntry
|
logEntry *InternalLogEntry
|
||||||
finalParsedCommand string
|
finalParsedCommand string
|
||||||
|
executor *Executor
|
||||||
}
|
}
|
||||||
|
|
||||||
// InternalLogEntry objects are created by an Executor, and represent the final
|
// InternalLogEntry objects are created by an Executor, and represent the final
|
||||||
// state of execution (even if the command is not executed). It's designed to be
|
// state of execution (even if the command is not executed). It's designed to be
|
||||||
// easily serializable.
|
// easily serializable.
|
||||||
type InternalLogEntry struct {
|
type InternalLogEntry struct {
|
||||||
Datetime string
|
DatetimeStarted string
|
||||||
Stdout string
|
DatetimeFinished string
|
||||||
Stderr string
|
Stdout string
|
||||||
TimedOut bool
|
Stderr string
|
||||||
ExitCode int32
|
StdoutBuffer io.ReadCloser
|
||||||
Tags []string
|
StderrBuffer io.ReadCloser
|
||||||
|
TimedOut bool
|
||||||
|
Blocked bool
|
||||||
|
ExitCode int32
|
||||||
|
Tags []string
|
||||||
|
ExecutionStarted bool
|
||||||
|
ExecutionFinished bool
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following two properties are obviously on Action normally, but it's useful
|
The following 3 properties are obviously on Action normally, but it's useful
|
||||||
that logs are lightweight (so we don't need to have an action associated to
|
that logs are lightweight (so we don't need to have an action associated to
|
||||||
logs, etc. Therefore, we duplicate those values here.
|
logs, etc. Therefore, we duplicate those values here.
|
||||||
*/
|
*/
|
||||||
ActionTitle string
|
ActionTitle string
|
||||||
ActionIcon string
|
ActionIcon string
|
||||||
|
UUID string
|
||||||
}
|
}
|
||||||
|
|
||||||
type executorStepFunc func(*ExecutionRequest) bool
|
type executorStepFunc func(*ExecutionRequest) bool
|
||||||
|
|
||||||
// Executor represents a helper class for executing commands. It's main method
|
|
||||||
// is ExecRequest
|
|
||||||
type Executor struct {
|
|
||||||
Logs []InternalLogEntry
|
|
||||||
|
|
||||||
chainOfCommand []executorStepFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecRequest processes an ExecutionRequest
|
|
||||||
func (e *Executor) ExecRequest(req *ExecutionRequest) *pb.StartActionResponse {
|
|
||||||
req.logEntry = &InternalLogEntry{
|
|
||||||
Datetime: time.Now().Format("2006-01-02 15:04:05"),
|
|
||||||
ActionTitle: req.ActionName,
|
|
||||||
Stdout: "",
|
|
||||||
Stderr: "",
|
|
||||||
ExitCode: -1337, // If an Action is not actually executed, this is the default exit code.
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, step := range e.chainOfCommand {
|
|
||||||
if !step(req) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Logs = append(e.Logs, *req.logEntry)
|
|
||||||
|
|
||||||
return &pb.StartActionResponse{
|
|
||||||
LogEntry: &pb.LogEntry{
|
|
||||||
ActionTitle: req.logEntry.ActionTitle,
|
|
||||||
ActionIcon: req.logEntry.ActionIcon,
|
|
||||||
Datetime: req.logEntry.Datetime,
|
|
||||||
Stderr: req.logEntry.Stderr,
|
|
||||||
Stdout: req.logEntry.Stdout,
|
|
||||||
TimedOut: req.logEntry.TimedOut,
|
|
||||||
ExitCode: req.logEntry.ExitCode,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultExecutor returns an Executor, with a sensible "chain of command" for
|
// DefaultExecutor returns an Executor, with a sensible "chain of command" for
|
||||||
// executing actions.
|
// executing actions.
|
||||||
func DefaultExecutor() *Executor {
|
func DefaultExecutor() *Executor {
|
||||||
e := Executor{}
|
e := Executor{}
|
||||||
|
e.Logs = make(map[string]*InternalLogEntry)
|
||||||
|
|
||||||
e.chainOfCommand = []executorStepFunc{
|
e.chainOfCommand = []executorStepFunc{
|
||||||
|
stepLogRequested,
|
||||||
stepFindAction,
|
stepFindAction,
|
||||||
|
stepConcurrencyCheck,
|
||||||
stepACLCheck,
|
stepACLCheck,
|
||||||
stepParseArgs,
|
stepParseArgs,
|
||||||
stepLogStart,
|
stepLogStart,
|
||||||
|
|
@ -103,6 +89,88 @@ func DefaultExecutor() *Executor {
|
||||||
return &e
|
return &e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type listener interface {
|
||||||
|
OnExecutionStarted(actionName string)
|
||||||
|
OnExecutionFinished(logEntry *InternalLogEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) AddListener(m listener) {
|
||||||
|
e.listeners = append(e.listeners, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecRequest processes an ExecutionRequest
|
||||||
|
func (e *Executor) ExecRequest(req *ExecutionRequest) *pb.StartActionResponse {
|
||||||
|
// req.UUID is now set by the client, so that they can track the request
|
||||||
|
// from start to finish. This means that a malicious client could send
|
||||||
|
// duplicate UUIDs (or just random strings), but this is the only way.
|
||||||
|
req.executor = e
|
||||||
|
req.logEntry = &InternalLogEntry{
|
||||||
|
DatetimeStarted: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
ActionTitle: req.ActionName,
|
||||||
|
UUID: req.UUID,
|
||||||
|
Stdout: "",
|
||||||
|
Stderr: "",
|
||||||
|
ExitCode: -1337, // If an Action is not actually executed, this is the default exit code.
|
||||||
|
ExecutionStarted: false,
|
||||||
|
ExecutionFinished: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Logs[req.UUID] = req.logEntry
|
||||||
|
|
||||||
|
for _, listener := range e.listeners {
|
||||||
|
listener.OnExecutionStarted(req.ActionName)
|
||||||
|
}
|
||||||
|
|
||||||
|
go e.execChain(req)
|
||||||
|
|
||||||
|
return &pb.StartActionResponse{
|
||||||
|
ExecutionUuid: req.UUID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) execChain(req *ExecutionRequest) {
|
||||||
|
for _, step := range e.chainOfCommand {
|
||||||
|
if !step(req) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.logEntry.ExecutionFinished = true
|
||||||
|
|
||||||
|
// This isn't a step, because we want to notify all listeners, irrespective
|
||||||
|
// of how many steps were actually executed.
|
||||||
|
notifyListeners(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConcurrentCount(req *ExecutionRequest) int {
|
||||||
|
concurrentCount := 0
|
||||||
|
|
||||||
|
for _, log := range req.executor.Logs {
|
||||||
|
if log.ActionTitle == req.ActionName && !log.ExecutionFinished {
|
||||||
|
concurrentCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return concurrentCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepConcurrencyCheck(req *ExecutionRequest) bool {
|
||||||
|
concurrentCount := getConcurrentCount(req)
|
||||||
|
|
||||||
|
// Note that the current execution is counted int the logs, so when checking we +1
|
||||||
|
if concurrentCount >= (req.action.MaxConcurrent + 1) {
|
||||||
|
msg := fmt.Sprintf("Blocked from executing. This would mean this action is running %d times concurrently, but this action has maxExecutions set to %d.", concurrentCount, req.action.MaxConcurrent)
|
||||||
|
|
||||||
|
log.Warnf(msg)
|
||||||
|
|
||||||
|
req.logEntry.Stdout = msg
|
||||||
|
req.logEntry.Blocked = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func stepFindAction(req *ExecutionRequest) bool {
|
func stepFindAction(req *ExecutionRequest) bool {
|
||||||
actualAction := req.Cfg.FindAction(req.ActionName)
|
actualAction := req.Cfg.FindAction(req.ActionName)
|
||||||
|
|
||||||
|
|
@ -142,10 +210,18 @@ func stepParseArgs(req *ExecutionRequest) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stepLogRequested(req *ExecutionRequest) bool {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"actionTitle": req.ActionName,
|
||||||
|
}).Infof("Action requested")
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func stepLogStart(req *ExecutionRequest) bool {
|
func stepLogStart(req *ExecutionRequest) bool {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"title": req.action.Title,
|
"actionTitle": req.action.Title,
|
||||||
"timeout": req.action.Timeout,
|
"timeout": req.action.Timeout,
|
||||||
}).Infof("Action starting")
|
}).Infof("Action starting")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
@ -153,16 +229,22 @@ func stepLogStart(req *ExecutionRequest) bool {
|
||||||
|
|
||||||
func stepLogFinish(req *ExecutionRequest) bool {
|
func stepLogFinish(req *ExecutionRequest) bool {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"title": req.action.Title,
|
"actionTitle": req.action.Title,
|
||||||
"stdout": req.logEntry.Stdout,
|
"stdout": req.logEntry.Stdout,
|
||||||
"stderr": req.logEntry.Stderr,
|
"stderr": req.logEntry.Stderr,
|
||||||
"timedOut": req.logEntry.TimedOut,
|
"timedOut": req.logEntry.TimedOut,
|
||||||
"exit": req.logEntry.ExitCode,
|
"exit": req.logEntry.ExitCode,
|
||||||
}).Infof("Action finished")
|
}).Infof("Action finished")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notifyListeners(req *ExecutionRequest) {
|
||||||
|
for _, listener := range req.executor.listeners {
|
||||||
|
listener.OnExecutionFinished(req.logEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
|
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
return exec.CommandContext(ctx, "cmd", "/C", finalParsedCommand)
|
return exec.CommandContext(ctx, "cmd", "/C", finalParsedCommand)
|
||||||
|
|
@ -181,8 +263,17 @@ func stepExec(req *ExecutionRequest) bool {
|
||||||
cmd := wrapCommandInShell(ctx, req.finalParsedCommand)
|
cmd := wrapCommandInShell(ctx, req.finalParsedCommand)
|
||||||
cmd.Stdout = &stdout
|
cmd.Stdout = &stdout
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
|
req.logEntry.StdoutBuffer, _ = cmd.StdoutPipe()
|
||||||
|
req.logEntry.StderrBuffer, _ = cmd.StderrPipe()
|
||||||
|
|
||||||
runerr := cmd.Run()
|
req.logEntry.ExecutionStarted = true
|
||||||
|
|
||||||
|
runerr := cmd.Start()
|
||||||
|
|
||||||
|
cmd.Wait()
|
||||||
|
|
||||||
|
// req.logEntry.Stdout = req.logEntry.StdoutBuffer.String()
|
||||||
|
// req.logEntry.Stderr = req.logEntry.StderrBuffer.String()
|
||||||
|
|
||||||
req.logEntry.ExitCode = int32(cmd.ProcessState.ExitCode())
|
req.logEntry.ExitCode = int32(cmd.ProcessState.ExitCode())
|
||||||
req.logEntry.Stdout = stdout.String()
|
req.logEntry.Stdout = stdout.String()
|
||||||
|
|
@ -197,6 +288,7 @@ func stepExec(req *ExecutionRequest) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
req.logEntry.Tags = req.Tags
|
req.logEntry.Tags = req.Tags
|
||||||
|
req.logEntry.DatetimeFinished = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
|
|
||||||
acl "github.com/OliveTin/OliveTin/internal/acl"
|
acl "github.com/OliveTin/OliveTin/internal/acl"
|
||||||
config "github.com/OliveTin/OliveTin/internal/config"
|
config "github.com/OliveTin/OliveTin/internal/config"
|
||||||
|
|
@ -19,7 +20,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type oliveTinAPI struct {
|
type oliveTinAPI struct {
|
||||||
pb.UnimplementedOliveTinApiServer
|
pb.UnimplementedOliveTinApiServiceServer
|
||||||
|
|
||||||
executor *executor.Executor
|
executor *executor.Executor
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +36,7 @@ func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest)
|
||||||
|
|
||||||
execReq := executor.ExecutionRequest{
|
execReq := executor.ExecutionRequest{
|
||||||
ActionName: req.ActionName,
|
ActionName: req.ActionName,
|
||||||
|
UUID: req.Uuid,
|
||||||
Arguments: args,
|
Arguments: args,
|
||||||
AuthenticatedUser: acl.UserFromContext(ctx, cfg),
|
AuthenticatedUser: acl.UserFromContext(ctx, cfg),
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
|
|
@ -43,6 +45,62 @@ func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest)
|
||||||
return api.executor.ExecRequest(&execReq), nil
|
return api.executor.ExecRequest(&execReq), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *oliveTinAPI) ExecutionStatus(ctx ctx.Context, req *pb.ExecutionStatusRequest) (*pb.ExecutionStatusResponse, error) {
|
||||||
|
res := &pb.ExecutionStatusResponse{}
|
||||||
|
|
||||||
|
logEntry, ok := api.executor.Logs[req.ExecutionUuid]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res.LogEntry = &pb.LogEntry{
|
||||||
|
ActionTitle: logEntry.ActionTitle,
|
||||||
|
ActionIcon: logEntry.ActionIcon,
|
||||||
|
DatetimeStarted: logEntry.DatetimeStarted,
|
||||||
|
DatetimeFinished: logEntry.DatetimeFinished,
|
||||||
|
Stdout: logEntry.Stdout,
|
||||||
|
Stderr: logEntry.Stderr,
|
||||||
|
TimedOut: logEntry.TimedOut,
|
||||||
|
Blocked: logEntry.Blocked,
|
||||||
|
ExitCode: logEntry.ExitCode,
|
||||||
|
Tags: logEntry.Tags,
|
||||||
|
ExecutionUuid: logEntry.UUID,
|
||||||
|
ExecutionStarted: logEntry.ExecutionStarted,
|
||||||
|
ExecutionFinished: logEntry.ExecutionFinished,
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
func (api *oliveTinAPI) WatchExecution(req *pb.WatchExecutionRequest, srv pb.OliveTinApi_WatchExecutionServer) error {
|
||||||
|
log.Infof("Watch")
|
||||||
|
|
||||||
|
if logEntry, ok := api.executor.Logs[req.ExecutionUuid]; !ok {
|
||||||
|
log.Errorf("Execution not found: %v", req.ExecutionUuid)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
if logEntry.ExecutionStarted {
|
||||||
|
for !logEntry.ExecutionCompleted {
|
||||||
|
tmp := make([]byte, 256)
|
||||||
|
|
||||||
|
red, err := io.ReadAtLeast(logEntry.StdoutBuffer, tmp, 1)
|
||||||
|
|
||||||
|
log.Infof("%v %v", red, err)
|
||||||
|
|
||||||
|
srv.Send(&pb.WatchExecutionUpdate{
|
||||||
|
Update: string(tmp),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
||||||
user := acl.UserFromContext(ctx, cfg)
|
user := acl.UserFromContext(ctx, cfg)
|
||||||
|
|
||||||
|
|
@ -62,19 +120,30 @@ func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.Ge
|
||||||
|
|
||||||
// TODO Limit to 10 entries or something to prevent browser lag.
|
// TODO Limit to 10 entries or something to prevent browser lag.
|
||||||
|
|
||||||
for _, logEntry := range api.executor.Logs {
|
for uuid, logEntry := range api.executor.Logs {
|
||||||
ret.Logs = append(ret.Logs, &pb.LogEntry{
|
ret.Logs = append(ret.Logs, &pb.LogEntry{
|
||||||
ActionTitle: logEntry.ActionTitle,
|
ActionTitle: logEntry.ActionTitle,
|
||||||
ActionIcon: logEntry.ActionIcon,
|
ActionIcon: logEntry.ActionIcon,
|
||||||
Datetime: logEntry.Datetime,
|
DatetimeStarted: logEntry.DatetimeStarted,
|
||||||
Stdout: logEntry.Stdout,
|
DatetimeFinished: logEntry.DatetimeFinished,
|
||||||
Stderr: logEntry.Stderr,
|
Stdout: logEntry.Stdout,
|
||||||
TimedOut: logEntry.TimedOut,
|
Stderr: logEntry.Stderr,
|
||||||
ExitCode: logEntry.ExitCode,
|
TimedOut: logEntry.TimedOut,
|
||||||
Tags: logEntry.Tags,
|
Blocked: logEntry.Blocked,
|
||||||
|
ExitCode: logEntry.ExitCode,
|
||||||
|
Tags: logEntry.Tags,
|
||||||
|
ExecutionUuid: uuid,
|
||||||
|
ExecutionStarted: logEntry.ExecutionStarted,
|
||||||
|
ExecutionFinished: logEntry.ExecutionFinished,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sorter := func(i, j int) bool {
|
||||||
|
return ret.Logs[i].DatetimeStarted < ret.Logs[j].DatetimeStarted
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(ret.Logs, sorter)
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +199,7 @@ func Start(globalConfig *config.Config, ex *executor.Executor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
grpcServer := grpc.NewServer()
|
grpcServer := grpc.NewServer()
|
||||||
pb.RegisterOliveTinApiServer(grpcServer, newServer(ex))
|
pb.RegisterOliveTinApiServiceServer(grpcServer, newServer(ex))
|
||||||
|
|
||||||
err = grpcServer.Serve(lis)
|
err = grpcServer.Serve(lis)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,11 @@ func actionsCfgToPb(cfgActions []config.Action, user *acl.AuthenticatedUser) *pb
|
||||||
|
|
||||||
func actionCfgToPb(action config.Action, user *acl.AuthenticatedUser) *pb.Action {
|
func actionCfgToPb(action config.Action, user *acl.AuthenticatedUser) *pb.Action {
|
||||||
btn := pb.Action{
|
btn := pb.Action{
|
||||||
Id: fmt.Sprintf("%x", md5.Sum([]byte(action.Title))),
|
Id: fmt.Sprintf("%x", md5.Sum([]byte(action.Title))),
|
||||||
Title: action.Title,
|
Title: action.Title,
|
||||||
Icon: action.Icon,
|
Icon: action.Icon,
|
||||||
CanExec: acl.IsAllowedExec(cfg, user, &action),
|
CanExec: acl.IsAllowedExec(cfg, user, &action),
|
||||||
|
PopupOnStart: action.PopupOnStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cfgArg := range action.Arguments {
|
for _, cfgArg := range action.Arguments {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func init() {
|
||||||
|
|
||||||
lis = bufconn.Listen(bufSize)
|
lis = bufconn.Listen(bufSize)
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
pb.RegisterOliveTinApiServer(s, newServer(ex))
|
pb.RegisterOliveTinApiServiceServer(s, newServer(ex))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := s.Serve(lis); err != nil {
|
if err := s.Serve(lis); err != nil {
|
||||||
|
|
@ -39,7 +39,7 @@ func bufDialer(context.Context, string) (net.Conn, error) {
|
||||||
return lis.Dial()
|
return lis.Dial()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*grpc.ClientConn, pb.OliveTinApiClient) {
|
func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*grpc.ClientConn, pb.OliveTinApiServiceClient) {
|
||||||
cfg = injectedConfig
|
cfg = injectedConfig
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
@ -50,7 +50,7 @@ func getNewTestServerAndClient(t *testing.T, injectedConfig *config.Config) (*gr
|
||||||
t.Fatalf("Failed to dial bufnet: %v", err)
|
t.Fatalf("Failed to dial bufnet: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := pb.NewOliveTinApiClient(conn)
|
client := pb.NewOliveTinApiServiceClient(conn)
|
||||||
|
|
||||||
return conn, client
|
return conn, client
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ func parseRequestMetadata(ctx context.Context, req *http.Request) metadata.MD {
|
||||||
return md
|
return md
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetGlobalRestConfig(config *config.Config) {
|
||||||
|
cfg = config
|
||||||
|
}
|
||||||
|
|
||||||
func startRestAPIServer(globalConfig *config.Config) error {
|
func startRestAPIServer(globalConfig *config.Config) error {
|
||||||
cfg = globalConfig
|
cfg = globalConfig
|
||||||
|
|
||||||
|
|
@ -76,7 +80,7 @@ func startRestAPIServer(globalConfig *config.Config) error {
|
||||||
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
||||||
Marshaler: &runtime.JSONPb{
|
Marshaler: &runtime.JSONPb{
|
||||||
MarshalOptions: protojson.MarshalOptions{
|
MarshalOptions: protojson.MarshalOptions{
|
||||||
UseProtoNames: true,
|
UseProtoNames: false, // eg: canExec for js instead of can_exec from protobuf
|
||||||
EmitUnpopulated: true,
|
EmitUnpopulated: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -84,7 +88,7 @@ func startRestAPIServer(globalConfig *config.Config) error {
|
||||||
)
|
)
|
||||||
opts := []grpc.DialOption{grpc.WithInsecure()}
|
opts := []grpc.DialOption{grpc.WithInsecure()}
|
||||||
|
|
||||||
err := gw.RegisterOliveTinApiHandlerFromEndpoint(ctx, mux, cfg.ListenAddressGrpcActions, opts)
|
err := gw.RegisterOliveTinApiServiceHandlerFromEndpoint(ctx, mux, cfg.ListenAddressGrpcActions, opts)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Could not register REST API Handler %v", err)
|
log.Errorf("Could not register REST API Handler %v", err)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,58 @@
|
||||||
package httpservers
|
package httpservers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseJwtToken(cookieValue string) (*jwt.Token, error) {
|
var (
|
||||||
|
pubKeyBytes []byte = nil
|
||||||
|
pubKey *rsa.PublicKey
|
||||||
|
)
|
||||||
|
|
||||||
|
func readPublicKey() error {
|
||||||
|
if pubKeyBytes != nil {
|
||||||
|
return nil // Already read.
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKeyBytes, err := os.ReadFile(cfg.AuthJwtPubKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't read public key from file %s", cfg.AuthJwtPubKeyPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the token is RSA (which we validated at the start of this function), the return type of this function actually has to be rsa.PublicKey!
|
||||||
|
pubKey, err = jwt.ParseRSAPublicKeyFromPEM(pubKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing public key object (from %s)", cfg.AuthJwtPubKeyPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseJwtTokenWithKey(cookieValue string) (*jwt.Token, error) {
|
||||||
|
err := readPublicKey()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwt.Parse(cookieValue, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"expected token algorithm '%v' but got '%v'",
|
||||||
|
jwt.SigningMethodRS256.Name,
|
||||||
|
token.Header)
|
||||||
|
}
|
||||||
|
return pubKey, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseJwtTokenWithoutKey(cookieValue string) (*jwt.Token, error) {
|
||||||
return jwt.Parse(cookieValue, func(token *jwt.Token) (interface{}, error) {
|
return jwt.Parse(cookieValue, func(token *jwt.Token) (interface{}, error) {
|
||||||
// Don't forget to validate the alg is what you expect:
|
// Don't forget to validate the alg is what you expect:
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
|
@ -20,6 +64,14 @@ func parseJwtToken(cookieValue string) (*jwt.Token, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseJwtToken(cookieValue string) (*jwt.Token, error) {
|
||||||
|
if cfg.AuthJwtPubKeyPath != "" { // activate this path only if pub key is specified
|
||||||
|
return parseJwtTokenWithKey(cookieValue)
|
||||||
|
} else {
|
||||||
|
return parseJwtTokenWithoutKey(cookieValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getClaimsFromJwtToken(cookieValue string) (jwt.MapClaims, error) {
|
func getClaimsFromJwtToken(cookieValue string) (jwt.MapClaims, error) {
|
||||||
token, err := parseJwtToken(cookieValue)
|
token, err := parseJwtToken(cookieValue)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
package httpservers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
config2 "github.com/OliveTin/OliveTin/internal/config"
|
||||||
|
"github.com/OliveTin/OliveTin/internal/cors"
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createKeys() (*rsa.PrivateKey, string) {
|
||||||
|
tmpFile, _ := os.CreateTemp(os.TempDir(), "olivetin-jwt-")
|
||||||
|
defer os.Remove(tmpFile.Name())
|
||||||
|
|
||||||
|
fmt.Println("Created File: " + tmpFile.Name())
|
||||||
|
|
||||||
|
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
pubKey := &privateKey.PublicKey
|
||||||
|
// https://stackoverflow.com/questions/13555085/save-and-load-crypto-rsa-privatekey-to-and-from-the-disk
|
||||||
|
pkixPubKey, _ := x509.MarshalPKIXPublicKey(pubKey)
|
||||||
|
pubPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "RSA PUBLIC KEY",
|
||||||
|
Bytes: pkixPubKey,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := os.WriteFile(tmpFile.Name(), pubPem, 0755); err != nil {
|
||||||
|
fmt.Printf("error when dumping pubKey: %s \n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return privateKey, tmpFile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBase(t *testing.T, expire int64, expectCode int) {
|
||||||
|
privateKey, publicKeyPath := createKeys()
|
||||||
|
|
||||||
|
// default config + overrides
|
||||||
|
config := config2.DefaultConfig()
|
||||||
|
config.AuthJwtPubKeyPath = publicKeyPath
|
||||||
|
config.AuthJwtClaimUsername = "sub"
|
||||||
|
config.AuthJwtClaimUserGroup = "olivetinGroup"
|
||||||
|
config.AuthJwtCookieName = "authorization_token"
|
||||||
|
SetGlobalRestConfig(config) // ugly, setting global var, we should pass configs as params to modules... :/
|
||||||
|
|
||||||
|
token := jwt.New(jwt.SigningMethodRS256)
|
||||||
|
|
||||||
|
claims := token.Claims.(jwt.MapClaims)
|
||||||
|
claims["nbf"] = time.Now().Unix() - 1000
|
||||||
|
claims["exp"] = time.Now().Unix() + expire
|
||||||
|
claims["sub"] = "test"
|
||||||
|
claims["olivetinGroup"] = "test"
|
||||||
|
|
||||||
|
tokenStr, _ := token.SignedString(privateKey)
|
||||||
|
|
||||||
|
// init mux endpoint like in restapi.go (but using dummy response handler)
|
||||||
|
mux := runtime.NewServeMux(
|
||||||
|
runtime.WithMetadata(parseRequestMetadata), // i am guessing this is critical middleware for authorizing request cookie
|
||||||
|
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
||||||
|
Marshaler: &runtime.JSONPb{
|
||||||
|
MarshalOptions: protojson.MarshalOptions{
|
||||||
|
UseProtoNames: true,
|
||||||
|
EmitUnpopulated: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
mux.HandlePath("GET", "/", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
|
||||||
|
username, usergroup := parseJwtCookie(r)
|
||||||
|
if username == "" {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
}
|
||||||
|
w.Write([]byte(fmt.Sprintf("username=%v, usergroup=%v", username, usergroup)))
|
||||||
|
})
|
||||||
|
|
||||||
|
// make server and attach handler
|
||||||
|
srv := &http.Server{Handler: cors.AllowCors(mux)}
|
||||||
|
lis, _ := net.Listen("tcp", ":1337")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := srv.Serve(lis); err != nil {
|
||||||
|
t.Errorf("couldn't start server: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// make http client and send request to myself
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("GET", "http://localhost:1337/", nil)
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: "authorization_token",
|
||||||
|
Value: tokenStr,
|
||||||
|
MaxAge: 300,
|
||||||
|
}
|
||||||
|
req.AddCookie(cookie)
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
assert.Equal(t, expectCode, -1)
|
||||||
|
} else {
|
||||||
|
defer res.Body.Close()
|
||||||
|
assert.Equal(t, expectCode, res.StatusCode)
|
||||||
|
body, _ := io.ReadAll(res.Body)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJWTSignatureVerificationSucceeds(t *testing.T) {
|
||||||
|
testBase(t, 1000, 200)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJWTSignatureVerificationFails(t *testing.T) {
|
||||||
|
testBase(t, -500, 403)
|
||||||
|
}
|
||||||
|
|
@ -10,10 +10,12 @@ away, and several other issues.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
config "github.com/OliveTin/OliveTin/internal/config"
|
config "github.com/OliveTin/OliveTin/internal/config"
|
||||||
|
"github.com/OliveTin/OliveTin/internal/websocket"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartSingleHTTPFrontend will create a reverse proxy that proxies the API
|
// StartSingleHTTPFrontend will create a reverse proxy that proxies the API
|
||||||
|
|
@ -37,8 +39,12 @@ func StartSingleHTTPFrontend(cfg *config.Config) {
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debugf("ui req: %q", r.URL)
|
if strings.Contains(r.Header.Get("Connection"), "Upgrade") {
|
||||||
webuiProxy.ServeHTTP(w, r)
|
websocket.HandleWebsocket(w, r)
|
||||||
|
} else {
|
||||||
|
log.Debugf("ui req: %q", r.URL)
|
||||||
|
webuiProxy.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package httpservers
|
package httpservers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
config "github.com/OliveTin/OliveTin/internal/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -9,6 +10,8 @@ import (
|
||||||
func TestGetWebuiDir(t *testing.T) {
|
func TestGetWebuiDir(t *testing.T) {
|
||||||
os.Chdir("../../") // go test sets the cwd to "httpservers" by default
|
os.Chdir("../../") // go test sets the cwd to "httpservers" by default
|
||||||
|
|
||||||
|
cfg = config.DefaultConfig()
|
||||||
|
|
||||||
dir := findWebuiDir()
|
dir := findWebuiDir()
|
||||||
|
|
||||||
assert.Equal(t, "./webui", dir, "Finding the webui dir")
|
assert.Equal(t, "./webui", dir, "Finding the webui dir")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
package websocket
|
||||||
|
|
||||||
|
import (
|
||||||
|
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||||
|
"github.com/OliveTin/OliveTin/internal/executor"
|
||||||
|
ws "github.com/gorilla/websocket"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var upgrader = ws.Upgrader{}
|
||||||
|
|
||||||
|
type WebsocketClient struct {
|
||||||
|
conn *ws.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
var clients []*WebsocketClient
|
||||||
|
|
||||||
|
var marshalOptions = protojson.MarshalOptions{
|
||||||
|
UseProtoNames: false, // eg: canExec for js instead of can_exec from protobuf
|
||||||
|
EmitUnpopulated: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var ExecutionListener WebsocketExecutionListener
|
||||||
|
|
||||||
|
type WebsocketExecutionListener struct{}
|
||||||
|
|
||||||
|
func (WebsocketExecutionListener) OnExecutionStarted(title string) {
|
||||||
|
/*
|
||||||
|
broadcast(ExecutionStarted{
|
||||||
|
Type: "ExecutionStarted",
|
||||||
|
Action: title,
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func (WebsocketExecutionListener) OnExecutionFinished(logEntry *executor.InternalLogEntry) {
|
||||||
|
le := &pb.LogEntry{
|
||||||
|
ActionTitle: logEntry.ActionTitle,
|
||||||
|
ActionIcon: logEntry.ActionIcon,
|
||||||
|
DatetimeStarted: logEntry.DatetimeStarted,
|
||||||
|
DatetimeFinished: logEntry.DatetimeFinished,
|
||||||
|
Stdout: logEntry.Stdout,
|
||||||
|
Stderr: logEntry.Stderr,
|
||||||
|
TimedOut: logEntry.TimedOut,
|
||||||
|
Blocked: logEntry.Blocked,
|
||||||
|
ExitCode: logEntry.ExitCode,
|
||||||
|
Tags: logEntry.Tags,
|
||||||
|
Uuid: logEntry.UUID,
|
||||||
|
ExecutionStarted: logEntry.ExecutionStarted,
|
||||||
|
ExecutionFinished: logEntry.ExecutionFinished,
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcast("ExecutionFinished", le)
|
||||||
|
}
|
||||||
|
|
||||||
|
func broadcast(messageType string, pbmsg *pb.LogEntry) {
|
||||||
|
payload, err := marshalOptions.Marshal(pbmsg)
|
||||||
|
|
||||||
|
// <EVIL>
|
||||||
|
// So, the websocket wants to encode messages using the same protomarshaller
|
||||||
|
// as the REST API - this gives consistency instead of using encoding/json
|
||||||
|
// and allows us to set specific marshalOptions.
|
||||||
|
//
|
||||||
|
// However, the protomarshaller will marshal the type, but the JavaScript at
|
||||||
|
// the other end has no idea what type this object is - as we're just sending
|
||||||
|
// it as JSON over the websocket.
|
||||||
|
//
|
||||||
|
// Therefore, we wrap the nicely marsheled bytes in a hacky JSON string
|
||||||
|
// literal and encode that string just with a byte array cast.
|
||||||
|
hackyMessageEnvelope := "{\"type\": \"" + messageType + "\", \"payload\": "
|
||||||
|
|
||||||
|
hackyMessage := []byte{}
|
||||||
|
hackyMessage = append(hackyMessage, []byte(hackyMessageEnvelope)...)
|
||||||
|
hackyMessage = append(hackyMessage, payload...)
|
||||||
|
hackyMessage = append(hackyMessage, []byte("}")...)
|
||||||
|
// </EVIL>
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("websocket marshal error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, client := range clients {
|
||||||
|
client.conn.WriteMessage(1, hackyMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *WebsocketClient) messageLoop() {
|
||||||
|
for {
|
||||||
|
mt, message, err := c.conn.ReadMessage()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("err: %v", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("websocket recv: %s %d", message, mt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleWebsocket(w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
c, err := upgrader.Upgrade(w, r, nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Websocket issue: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// defer c.Close()
|
||||||
|
|
||||||
|
wsclient := &WebsocketClient{
|
||||||
|
conn: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
clients = append(clients, wsclient)
|
||||||
|
|
||||||
|
go wsclient.messageLoop()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
@ -62,38 +62,87 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer title = "footer">
|
<footer title = "footer">
|
||||||
<p><img title = "application icon" src = "OliveTinLogo.png" height = "1em" class = "logo" /> OliveTin</p>
|
<p><img title = "application icon" src = "OliveTinLogo.png" alt = "OliveTin logo" height = "1em" class = "logo" /> OliveTin</p>
|
||||||
<p>
|
<p>
|
||||||
<a href = "https://docs.olivetin.app" target = "_new">Documentation</a> |
|
<a href = "https://docs.olivetin.app" target = "_new">Documentation</a> |
|
||||||
<a href = "https://github.com/OliveTin/OliveTin/issues/new/choose" target = "_new">Raise an issue on GitHub</a> |
|
<a href = "https://github.com/OliveTin/OliveTin/issues/new/choose" target = "_new">Raise an issue on GitHub</a> |
|
||||||
<span id = "currentVersion">Version: ?</p>
|
<span>Version: <span id = "currentVersion">?</span></span> |
|
||||||
|
<span>Server connection: <span id = "serverConnection">?</span></span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
<a id = "available-version" href = "http://olivetin.app" target = "_blank" hidden>?</a>
|
<a id = "available-version" href = "http://olivetin.app" target = "_blank" hidden>?</a>
|
||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<dialog id = "executionResults">
|
||||||
|
<div class = "action-header">
|
||||||
|
<span class = "icon" role = "icon"></span>
|
||||||
|
|
||||||
|
<h2>Log:
|
||||||
|
<span class = "title">?</span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<strong>Started: </strong><span class = "datetimeStarted">unknown</span>.
|
||||||
|
<strong>Finished: </strong><span class = "datetimeFinished">unknown</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Exit Code: </strong><span class = "exitCode">unknown</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Status: </strong><span class = "status">unknown</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>stdout</summary>
|
||||||
|
<pre class = "stdout">
|
||||||
|
?
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>stderr</summary>
|
||||||
|
<pre class = "stderr">
|
||||||
|
?
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<form method = "dialog">
|
||||||
|
<button name = "cancel">Close</button>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
<template id = "tplArgumentForm">
|
<template id = "tplArgumentForm">
|
||||||
<form class = "action-arguments">
|
<dialog>
|
||||||
<div class = "wrapper">
|
<form class = "action-arguments">
|
||||||
<div>
|
<div class = "wrapper">
|
||||||
<span class = "icon" role = "icon"></span>
|
<div class = "action-header">
|
||||||
<h2>Argument form</h2>
|
<span class = "icon" role = "icon"></span>
|
||||||
</div>
|
<h2>Argument form</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class = "arguments"></div>
|
<div class = "arguments"></div>
|
||||||
|
|
||||||
<div class = "buttons">
|
<div class = "buttons">
|
||||||
<input name = "start" type = "submit" value = "Start">
|
<input name = "start" type = "submit" value = "Start">
|
||||||
<button name = "cancel">Cancel</button>
|
<button name = "cancel">Cancel</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
<form>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id = "tplActionButton">
|
<template id = "tplActionButton">
|
||||||
<button>
|
<div>
|
||||||
<span role = "icon" title = "button icon" class = "icon">💩</span>
|
<button>
|
||||||
<p role = "title" class = "title">Untitled Button</p>
|
<span role = "icon" title = "button icon" class = "icon">💩</span>
|
||||||
</button>
|
<span role = "title" class = "title">Untitled Button</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class = "executions">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id = "tplLogRow">
|
<template id = "tplLogRow">
|
||||||
|
|
@ -129,7 +178,10 @@
|
||||||
to at least display a helpful error message if we can't use OliveTin.
|
to at least display a helpful error message if we can't use OliveTin.
|
||||||
*/
|
*/
|
||||||
function showBigError (type, friendlyType, message) {
|
function showBigError (type, friendlyType, message) {
|
||||||
clearInterval(window.buttonInterval)
|
for (const oldError of document.querySelectorAll('div.error').values()) {
|
||||||
|
window.old = oldError;
|
||||||
|
oldError.remove();
|
||||||
|
}
|
||||||
|
|
||||||
console.error('Error ' + type + ': ', message)
|
console.error('Error ' + type + ': ', message)
|
||||||
|
|
||||||
|
|
@ -146,5 +198,6 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type = "module" src = "main.js"></script>
|
<script type = "module" src = "main.js"></script>
|
||||||
|
<script type = "module" src = "js/websocket.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { marshalLogsJsonToHtml } from './marshaller.js'
|
|
||||||
import './ArgumentForm.js'
|
import './ArgumentForm.js'
|
||||||
|
import './ExecutionButton.js'
|
||||||
|
|
||||||
class ActionButton extends window.HTMLElement {
|
class ActionButton extends window.HTMLElement {
|
||||||
constructFromJson (json) {
|
constructFromJson (json) {
|
||||||
|
|
@ -25,6 +25,7 @@ class ActionButton extends window.HTMLElement {
|
||||||
})
|
})
|
||||||
|
|
||||||
document.body.appendChild(frm)
|
document.body.appendChild(frm)
|
||||||
|
frm.querySelector('dialog').showModal()
|
||||||
} else {
|
} else {
|
||||||
this.startAction()
|
this.startAction()
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +33,8 @@ class ActionButton extends window.HTMLElement {
|
||||||
|
|
||||||
this.updateFromJson(json)
|
this.updateFromJson(json)
|
||||||
|
|
||||||
this.updateDom()
|
this.domTitle.innerText = this.btn.title
|
||||||
|
this.domIcon.innerHTML = this.unicodeIcon
|
||||||
|
|
||||||
this.setAttribute('id', 'actionButton_' + json.id)
|
this.setAttribute('id', 'actionButton_' + json.id)
|
||||||
}
|
}
|
||||||
|
|
@ -52,20 +54,27 @@ class ActionButton extends window.HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
startAction (actionArgs) {
|
startAction (actionArgs) {
|
||||||
this.btn.disabled = true
|
// this.btn.disabled = true
|
||||||
this.isWaiting = true
|
// this.isWaiting = true
|
||||||
this.updateDom()
|
// this.updateDom()
|
||||||
this.btn.classList = [] // Removes old animation classes
|
this.btn.classList = [] // Removes old animation classes
|
||||||
|
|
||||||
if (actionArgs === undefined) {
|
if (actionArgs === undefined) {
|
||||||
actionArgs = []
|
actionArgs = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UUIDs are create client side, so that we can setup a "execution-button"
|
||||||
|
// to track the execution before we send the request to the server.
|
||||||
const startActionArgs = {
|
const startActionArgs = {
|
||||||
actionName: this.btn.title,
|
actionName: this.btn.title,
|
||||||
arguments: actionArgs
|
arguments: actionArgs,
|
||||||
|
uuid: window.crypto.randomUUID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const btnExecution = document.createElement('execution-button')
|
||||||
|
btnExecution.constructFromJson(startActionArgs.uuid)
|
||||||
|
this.querySelector('div.executions').appendChild(btnExecution)
|
||||||
|
|
||||||
window.fetch(this.actionCallUrl, {
|
window.fetch(this.actionCallUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -80,45 +89,12 @@ class ActionButton extends window.HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then((json) => {
|
).then((json) => {
|
||||||
marshalLogsJsonToHtml({ logs: [json.logEntry] })
|
// The button used to wait for the action to finish, but now it is fire & forget
|
||||||
|
|
||||||
if (json.logEntry.timedOut) {
|
|
||||||
this.onActionResult('action-timeout', 'Timed out')
|
|
||||||
} else if (json.logEntry.exitCode === -1337) {
|
|
||||||
this.onActionError('Error')
|
|
||||||
} else if (json.logEntry.exitCode !== 0) {
|
|
||||||
this.onActionResult('action-nonzero-exit', 'Exit code ' + json.logEntry.exitCode)
|
|
||||||
} else {
|
|
||||||
this.onActionResult('action-success', 'Success!')
|
|
||||||
}
|
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.onActionError(err)
|
this.onActionError(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onActionResult (cssClass, temporaryStatusMessage) {
|
|
||||||
this.btn.disabled = false
|
|
||||||
this.temporaryStatusMessage = '[ ' + temporaryStatusMessage + ' ]'
|
|
||||||
this.updateDom()
|
|
||||||
this.btn.classList.add(cssClass)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.btn.classList.remove(cssClass)
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
onActionError (err) {
|
|
||||||
console.error('callback error', err)
|
|
||||||
this.btn.disabled = false
|
|
||||||
this.isWaiting = false
|
|
||||||
this.updateDom()
|
|
||||||
this.btn.classList.add('action-failed')
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.btn.classList.remove('action-failed')
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructDomFromTemplate () {
|
constructDomFromTemplate () {
|
||||||
const tpl = document.getElementById('tplActionButton')
|
const tpl = document.getElementById('tplActionButton')
|
||||||
const content = tpl.content.cloneNode(true)
|
const content = tpl.content.cloneNode(true)
|
||||||
|
|
@ -134,27 +110,6 @@ class ActionButton extends window.HTMLElement {
|
||||||
this.domTitle = this.btn.querySelector('.title')
|
this.domTitle = this.btn.querySelector('.title')
|
||||||
this.domIcon = this.btn.querySelector('.icon')
|
this.domIcon = this.btn.querySelector('.icon')
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDom () {
|
|
||||||
if (this.temporaryStatusMessage != null) {
|
|
||||||
this.domTitle.innerText = this.temporaryStatusMessage
|
|
||||||
this.domTitle.classList.add('temporary-status-message')
|
|
||||||
this.isWaiting = false
|
|
||||||
this.disabled = false
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.temporaryStatusMessage = null
|
|
||||||
this.domTitle.classList.remove('temporary-status-message')
|
|
||||||
this.updateDom()
|
|
||||||
}, 2000)
|
|
||||||
} else if (this.isWaiting) {
|
|
||||||
this.domTitle.innerText = 'Waiting...'
|
|
||||||
} else {
|
|
||||||
this.domTitle.innerText = this.btn.title
|
|
||||||
}
|
|
||||||
|
|
||||||
this.domIcon.innerHTML = this.unicodeIcon
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.customElements.define('action-button', ActionButton)
|
window.customElements.define('action-button', ActionButton)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
import { ExecutionDialog } from './ExecutionDialog.js'
|
||||||
|
|
||||||
|
class ExecutionButton extends window.HTMLElement {
|
||||||
|
constructFromJson (json) {
|
||||||
|
this.executionUuid = json
|
||||||
|
|
||||||
|
this.appendChild(document.createElement('button'))
|
||||||
|
this.isWaiting = true
|
||||||
|
|
||||||
|
this.setAttribute('id', 'execution-' + json)
|
||||||
|
|
||||||
|
this.btn = this.querySelector('button')
|
||||||
|
this.btn.innerText = 'Executing...'
|
||||||
|
this.btn.onclick = () => {
|
||||||
|
this.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show () {
|
||||||
|
if (window.executionDialog === undefined) {
|
||||||
|
window.executionDialog = new ExecutionDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
const executionStatusArgs = {
|
||||||
|
executionUuid: this.executionUuid
|
||||||
|
}
|
||||||
|
|
||||||
|
window.executionDialog.constructFromJson(this.executionUuid)
|
||||||
|
window.executionDialog.show()
|
||||||
|
|
||||||
|
window.fetch(window.restBaseUrl + 'ExecutionStatus', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(executionStatusArgs)
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
return res.json()
|
||||||
|
} else {
|
||||||
|
throw new Error(res.statusText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).then((json) => {
|
||||||
|
window.executionDialog.renderResult(json)
|
||||||
|
}).catch(err => {
|
||||||
|
window.executionDialog.renderError(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onFinished (LogEntry) {
|
||||||
|
if (LogEntry.timedOut) {
|
||||||
|
this.onActionResult('action-timeout', 'Timed out')
|
||||||
|
} else if (LogEntry.blocked) {
|
||||||
|
this.onActionResult('action-blocked', 'Blocked!')
|
||||||
|
} else if (LogEntry.exitCode !== 0) {
|
||||||
|
this.onActionResult('action-nonzero-exit', 'Exit code ' + LogEntry.exitCode)
|
||||||
|
} else {
|
||||||
|
this.onActionResult('action-success', 'Success!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onActionResult (cssClass, temporaryStatusMessage) {
|
||||||
|
this.temporaryStatusMessage = '[ ' + temporaryStatusMessage + ' ]'
|
||||||
|
this.updateDom()
|
||||||
|
this.btn.classList.add(cssClass)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.btn.classList.remove(cssClass)
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
onActionError (err) {
|
||||||
|
console.error('callback error', err)
|
||||||
|
this.btn.disabled = false
|
||||||
|
this.isWaiting = false
|
||||||
|
this.updateDom()
|
||||||
|
this.btn.classList.add('action-failed')
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.btn.classList.remove('action-failed')
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDom () {
|
||||||
|
if (this.temporaryStatusMessage != null) {
|
||||||
|
this.btn.innerText = this.temporaryStatusMessage
|
||||||
|
this.btn.classList.add('temporary-status-message')
|
||||||
|
this.isWaiting = false
|
||||||
|
this.disabled = false
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.temporaryStatusMessage = null
|
||||||
|
this.btn.classList.remove('temporary-status-message')
|
||||||
|
this.updateDom()
|
||||||
|
}, 2000)
|
||||||
|
} else if (this.isWaiting) {
|
||||||
|
this.btn.innerText = 'Waiting...'
|
||||||
|
} else {
|
||||||
|
this.btn.innerText = 'Finished'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('execution-button', ExecutionButton)
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// This ExecutionDialog is NOT a custom HTML element, but rather just picks up
|
||||||
|
// the <dialog /> element out of index.html and just re-uses that - as only
|
||||||
|
// one dialog can be shown at a time.
|
||||||
|
export class ExecutionDialog {
|
||||||
|
constructFromJson (json) {
|
||||||
|
this.executionUuid = json
|
||||||
|
|
||||||
|
this.dlg = document.querySelector('dialog#executionResults')
|
||||||
|
|
||||||
|
this.domIcon = this.dlg.querySelector('.icon')
|
||||||
|
this.domTitle = this.dlg.querySelector('.title')
|
||||||
|
this.domStdout = this.dlg.querySelector('.stdout')
|
||||||
|
this.domStderr = this.dlg.querySelector('.stderr')
|
||||||
|
this.domDatetimeStarted = this.dlg.querySelector('.datetimeStarted')
|
||||||
|
this.domDatetimeFinished = this.dlg.querySelector('.datetimeFinished')
|
||||||
|
this.domExitCode = this.dlg.querySelector('.exitCode')
|
||||||
|
this.domStatus = this.dlg.querySelector('.status')
|
||||||
|
}
|
||||||
|
|
||||||
|
show () {
|
||||||
|
this.dlg.showModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderResult (res) {
|
||||||
|
this.executionUuid = res.logEntry.executionUuid
|
||||||
|
|
||||||
|
if (res.logEntry.executionFinished) {
|
||||||
|
this.domStatus.innerText = 'Completed'
|
||||||
|
this.domDatetimeFinished.innerText = res.logEntry.datetimeFinished
|
||||||
|
|
||||||
|
if (res.logEntry.blocked) {
|
||||||
|
this.domStatus.innerText = 'Blocked'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.logEntry.timedOut) {
|
||||||
|
this.domExitCode.innerText = 'Timed out'
|
||||||
|
this.domStatus.innerText = 'Timed out'
|
||||||
|
} else {
|
||||||
|
this.domExitCode.innerText = res.logEntry.exitCode
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.domDatetimeFinished.innerText = 'Still running...'
|
||||||
|
this.domExitCode.innerText = 'Still running...'
|
||||||
|
this.domStatus.innerText = 'Still running...'
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domIcon.innerHTML = res.logEntry.actionIcon
|
||||||
|
this.domTitle.innerText = res.logEntry.actionTitle
|
||||||
|
|
||||||
|
this.domStdout.innerText = res.logEntry.stdout
|
||||||
|
|
||||||
|
if (res.logEntry.stderr === '') {
|
||||||
|
this.domStderr.parentElement.hidden = true
|
||||||
|
this.domStderr.innerText = res.logEntry.stderr
|
||||||
|
} else {
|
||||||
|
this.domStderr.parentElement.hidden = false
|
||||||
|
this.domStderr.innerText = res.logEntry.stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domDatetimeStarted.innerText = res.logEntry.datetimeStarted
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError (err) {
|
||||||
|
this.dlg.querySelector('pre').innerText = JSON.stringify(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ export function marshalLogsJsonToHtml (json) {
|
||||||
logTableExitCode += ' (timed out)'
|
logTableExitCode += ' (timed out)'
|
||||||
}
|
}
|
||||||
|
|
||||||
row.querySelector('.timestamp').innerText = logEntry.datetime
|
row.querySelector('.timestamp').innerText = logEntry.datetimeStarted
|
||||||
row.querySelector('.content').innerText = logEntry.actionTitle
|
row.querySelector('.content').innerText = logEntry.actionTitle
|
||||||
row.querySelector('.icon').innerHTML = logEntry.actionIcon
|
row.querySelector('.icon').innerHTML = logEntry.actionIcon
|
||||||
row.querySelector('pre.stdout').innerText = logEntry.stdout
|
row.querySelector('pre.stdout').innerText = logEntry.stdout
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { marshalLogsJsonToHtml } from './marshaller.js'
|
||||||
|
|
||||||
|
window.ws = null
|
||||||
|
|
||||||
|
export function checkWebsocketConnection () {
|
||||||
|
if (window.ws === null || window.ws.readyState === 3) {
|
||||||
|
reconnectWebsocket()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reconnectWebsocket () {
|
||||||
|
window.websocketAvailable = false
|
||||||
|
|
||||||
|
let proto = 'ws:'
|
||||||
|
|
||||||
|
if (window.location.protocol === 'https:') {
|
||||||
|
proto = 'wss:'
|
||||||
|
}
|
||||||
|
|
||||||
|
const websocketConnectionUrl = proto + window.location.host + '/websocket'
|
||||||
|
const ws = window.ws = new WebSocket(websocketConnectionUrl)
|
||||||
|
|
||||||
|
ws.addEventListener('open', websocketOnOpen)
|
||||||
|
ws.addEventListener('message', websocketOnMessage)
|
||||||
|
ws.addEventListener('error', websocketOnError)
|
||||||
|
ws.addEventListener('close', websocketOnClose)
|
||||||
|
}
|
||||||
|
|
||||||
|
function websocketOnOpen (evt) {
|
||||||
|
window.websocketAvailable = true
|
||||||
|
|
||||||
|
window.ws.send('monitor')
|
||||||
|
|
||||||
|
window.refreshLoop()
|
||||||
|
}
|
||||||
|
|
||||||
|
function websocketOnMessage (msg) {
|
||||||
|
// FIXME check msg status is OK
|
||||||
|
const j = JSON.parse(msg.data)
|
||||||
|
|
||||||
|
switch (j.type) {
|
||||||
|
case 'ExecutionFinished':
|
||||||
|
updatePageAfterFinished(j.payload)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
window.showBigError('Unknown message type from server: ' + j.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePageAfterFinished (logEntry) {
|
||||||
|
document.querySelector('execution-button#execution-' + logEntry.uuid).onFinished(logEntry)
|
||||||
|
|
||||||
|
marshalLogsJsonToHtml({
|
||||||
|
logs: [logEntry]
|
||||||
|
})
|
||||||
|
|
||||||
|
// If the current execution dialog is open, update that too
|
||||||
|
if (window.executionDialog != null && window.executionDialog.dlg.open && window.executionDialog.executionUuid === logEntry.uuid) {
|
||||||
|
window.executionDialog.renderResult({
|
||||||
|
logEntry: logEntry
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function websocketOnError (err) {
|
||||||
|
window.websocketAvailable = false
|
||||||
|
window.refreshLoop()
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
function websocketOnClose () {
|
||||||
|
window.websocketAvailable = false
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import { marshalActionButtonsJsonToHtml, marshalLogsJsonToHtml } from './js/marshaller.js'
|
import { marshalActionButtonsJsonToHtml, marshalLogsJsonToHtml } from './js/marshaller.js'
|
||||||
|
import { checkWebsocketConnection } from './js/websocket.js'
|
||||||
|
|
||||||
function showSection (name) {
|
function showSection (name) {
|
||||||
for (const otherName of ['Actions', 'Logs']) {
|
for (const otherName of ['Actions', 'Logs']) {
|
||||||
|
|
@ -19,15 +20,42 @@ function setupSections () {
|
||||||
showSection('Actions')
|
showSection('Actions')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refreshLoop () {
|
||||||
|
if (window.websocketAvailable) {
|
||||||
|
document.querySelector('#serverConnection').classList.remove('error')
|
||||||
|
document.querySelector('#serverConnection').innerText = 'websocket'
|
||||||
|
|
||||||
|
// Websocket updates are streamed live, not updated on a loop.
|
||||||
|
} else if (window.restAvailable) {
|
||||||
|
// Fallback to rest, but try to reconnect the websocket anyway.
|
||||||
|
|
||||||
|
fetchGetDashboardComponents()
|
||||||
|
checkWebsocketConnection()
|
||||||
|
|
||||||
|
document.querySelector('#serverConnection').classList.remove('error')
|
||||||
|
document.querySelector('#serverConnection').innerText = 'rest'
|
||||||
|
|
||||||
|
fetchGetLogs()
|
||||||
|
} else {
|
||||||
|
document.querySelector('#serverConnection').innerText = 'disconnected, trying to reconnect...'
|
||||||
|
document.querySelector('#serverConnection').classList.add('error')
|
||||||
|
|
||||||
|
// Still try to fetch the dashboard, if successfull window.restAvailable = true
|
||||||
|
fetchGetDashboardComponents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fetchGetDashboardComponents () {
|
function fetchGetDashboardComponents () {
|
||||||
window.fetch(window.restBaseUrl + 'GetDashboardComponents', {
|
window.fetch(window.restBaseUrl + 'GetDashboardComponents', {
|
||||||
cors: 'cors'
|
cors: 'cors'
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
return res.json()
|
return res.json()
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
window.restAvailable = true
|
||||||
marshalActionButtonsJsonToHtml(res)
|
marshalActionButtonsJsonToHtml(res)
|
||||||
}).catch(err => {
|
}).catch(() => { // err is 1st arg
|
||||||
window.showBigError('fetch-buttons', 'getting buttons', err, 'blat')
|
window.restAvailable = false
|
||||||
|
// window.showBigError('fetch-buttons', 'getting buttons', err, 'blat')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,7 +83,7 @@ function processWebuiSettingsJson (settings) {
|
||||||
document.head.appendChild(themeCss)
|
document.head.appendChild(themeCss)
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector('#currentVersion').innerText = 'Version: ' + settings.CurrentVersion
|
document.querySelector('#currentVersion').innerText = settings.CurrentVersion
|
||||||
|
|
||||||
if (settings.ShowNewVersions && settings.AvailableVersion !== 'none') {
|
if (settings.ShowNewVersions && settings.AvailableVersion !== 'none') {
|
||||||
document.querySelector('#available-version').innerText = 'New Version Available: ' + settings.AvailableVersion
|
document.querySelector('#available-version').innerText = 'New Version Available: ' + settings.AvailableVersion
|
||||||
|
|
@ -80,10 +108,11 @@ function main () {
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
processWebuiSettingsJson(res)
|
processWebuiSettingsJson(res)
|
||||||
|
|
||||||
fetchGetDashboardComponents()
|
window.restAvailable = true
|
||||||
fetchGetLogs()
|
window.refreshLoop = refreshLoop
|
||||||
|
window.refreshLoop()
|
||||||
|
|
||||||
window.buttonInterval = setInterval(fetchGetDashboardComponents, 3000)
|
setInterval(refreshLoop, 3000)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
window.showBigError('fetch-webui-settings', 'getting webui settings', err)
|
window.showBigError('fetch-webui-settings', 'getting webui settings', err)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1053,9 +1053,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-node/node_modules/semver": {
|
"node_modules/eslint-plugin-node/node_modules/semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
|
|
@ -2639,9 +2639,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/read-pkg/node_modules/semver": {
|
"node_modules/read-pkg/node_modules/semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver"
|
"semver": "bin/semver"
|
||||||
|
|
@ -2796,9 +2796,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.3.8",
|
"version": "7.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
|
|
@ -4155,9 +4155,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5281,9 +5281,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"type-fest": {
|
"type-fest": {
|
||||||
|
|
@ -5399,9 +5399,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.8",
|
"version": "7.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
min-width: 600px;
|
||||||
|
text-align: left;
|
||||||
|
padding: 1em;
|
||||||
|
box-shadow: 0 0 6px 0 #444;
|
||||||
|
}
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +127,7 @@ span[role="icon"] {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
form span[role="icon"],
|
.action-header span[role="icon"],
|
||||||
tr.log-row span[role="icon"] {
|
tr.log-row span[role="icon"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-right: 0.2em;
|
padding-right: 0.2em;
|
||||||
|
|
@ -128,6 +135,9 @@ tr.log-row span[role="icon"] {
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
background-color: salmon;
|
background-color: salmon;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.error {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,6 +156,7 @@ div.entity {
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +196,11 @@ input[type="submit"]:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.executions button {
|
||||||
|
margin-top: .2em;
|
||||||
|
margin-bottom: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
fieldset#section-switcher {
|
fieldset#section-switcher {
|
||||||
border: 0;
|
border: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
@ -254,6 +270,14 @@ button.active-section {
|
||||||
20% { background-color: cyan; }
|
20% { background-color: cyan; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-blocked {
|
||||||
|
animation: kf-action-blocked 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes kf-action-blocked {
|
||||||
|
20% { background-color: purple; }
|
||||||
|
}
|
||||||
|
|
||||||
footer,
|
footer,
|
||||||
footer a {
|
footer a {
|
||||||
color: black;
|
color: black;
|
||||||
|
|
@ -282,21 +306,9 @@ details[open] {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.action-arguments {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
padding: 1em;
|
|
||||||
box-shadow: 0 0 6px 0 #aaa;
|
|
||||||
background-color: #dee3e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
form div.wrapper {
|
form div.wrapper {
|
||||||
border-radius: 1em;
|
|
||||||
box-shadow: 0 0 10px 0 #444;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid #999;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue