diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 672bb521a..068b4aa72 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -119,7 +119,7 @@ jobs: run: | $(go env GOPATH)/bin/ziti-ci configure-git $(go env GOPATH)/bin/ziti-ci generate-build-info common/version/info_generated.go version - pushd network-tests && go install ./... && popd + pushd zititest && go install ./... && popd go install -tags=all,tests ./... - name: Create Zitilab Bindings @@ -148,7 +148,7 @@ jobs: run: | echo "ZITI_ROOT=$(go env GOPATH)/bin" >> "$GITHUB_ENV" $(go env GOPATH)/bin/simple-transfer run - pushd network-tests && go test -v ./tests/... && popd + pushd zititest && go test -v ./tests/... && popd - name: Test Ziti Command Teardown if: always() diff --git a/go.mod b/go.mod index 726e1bf45..e7ef0a87e 100644 --- a/go.mod +++ b/go.mod @@ -21,16 +21,16 @@ require ( github.com/jedib0t/go-pretty/v6 v6.4.0 github.com/michaelquigley/pfxlog v0.6.10 github.com/openziti/agent v1.0.13 - github.com/openziti/channel/v2 v2.0.78 - github.com/openziti/edge v0.24.309 + github.com/openziti/channel/v2 v2.0.79 + github.com/openziti/edge v0.24.313 github.com/openziti/edge-api v0.25.24 github.com/openziti/fabric v0.23.29 - github.com/openziti/foundation/v2 v2.0.24 - github.com/openziti/identity v1.0.54 + github.com/openziti/foundation/v2 v2.0.25 + github.com/openziti/identity v1.0.55 github.com/openziti/runzmd v1.0.24 - github.com/openziti/sdk-golang v0.20.51 - github.com/openziti/storage v0.2.6 - github.com/openziti/transport/v2 v2.0.88 + github.com/openziti/sdk-golang v0.20.54 + github.com/openziti/storage v0.2.7 + github.com/openziti/transport/v2 v2.0.89 github.com/openziti/xweb/v2 v2.0.2 github.com/openziti/ziti-db-explorer v1.1.1 github.com/pkg/errors v0.9.1 @@ -41,7 +41,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 go.etcd.io/bbolt v1.3.7 golang.org/x/net v0.10.0 google.golang.org/grpc v1.42.0 @@ -142,7 +142,7 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openziti/dilithium v0.3.3 // indirect github.com/openziti/jwks v1.0.3 // indirect - github.com/openziti/metrics v1.2.25 // indirect + github.com/openziti/metrics v1.2.26 // indirect github.com/openziti/secretstream v0.1.8 // indirect github.com/openziti/x509-claims v1.0.3 // indirect github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect diff --git a/go.sum b/go.sum index 8a255f275..8a6362178 100644 --- a/go.sum +++ b/go.sum @@ -721,34 +721,34 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openziti/agent v1.0.13 h1:RptJCEANPb904cDqlP7IYfBI+he8EyosimYhG7bp9D0= github.com/openziti/agent v1.0.13/go.mod h1:CRbwhhnpsoDw0BxZsCRyQUozoRnGzH7+wuQVp1h4qX8= -github.com/openziti/channel/v2 v2.0.78 h1:zY6olGzk0i7RdwnQQYV4J3aJmtuWqpTNUpbCKrghdFA= -github.com/openziti/channel/v2 v2.0.78/go.mod h1:yajD/OlGYESMURbogY+myEUZ49fWERPbIhU6kcDnQHE= +github.com/openziti/channel/v2 v2.0.79 h1:pjbMmllLu1K3RzvX3K+FJK09bewrL5ZJGEL2cZiPmuM= +github.com/openziti/channel/v2 v2.0.79/go.mod h1:NOwAKC9nTZi41njN/4iRNWpGpt4psu5jjhv8bA9FbwE= github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k= github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo= -github.com/openziti/edge v0.24.309 h1:EGZZ7GqI6/2y8zoNc0Tb11DpHtDG3YTNMUChulFTDL4= -github.com/openziti/edge v0.24.309/go.mod h1:UDlCvgpuzQ6FFugSK0Sim7214c1O+7ahiOX5tvhJaP4= +github.com/openziti/edge v0.24.313 h1:r8Foxel03S4c9mlkbS5cSS0DxSVjEzpLkkX1nkvI+4Q= +github.com/openziti/edge v0.24.313/go.mod h1:5gH8JPtRYO867mhEPwWBqNqYnZXFIGDvmymn180nhKM= github.com/openziti/edge-api v0.25.24 h1:XrF3AtF9mnJXgG7rSV2M50Dj/EKUkBUaDdb9/n2TDHI= github.com/openziti/edge-api v0.25.24/go.mod h1:rmEkj8jAkBTUhhgE/GFXije6bpFbd2P9TzdxTqZlXI8= github.com/openziti/fabric v0.23.29 h1:FbAeUhfkNGYPNCYo3BFzRByvMTKhscxJEQxYU0BJJdA= github.com/openziti/fabric v0.23.29/go.mod h1:/M8URo+qloi39qG0QWvXTgtpiPPneNYOjR+VvywS0cw= -github.com/openziti/foundation/v2 v2.0.24 h1:cNJCbh4o9E+7mtSUDo7ZBuMoPjJAilDWgr7X8ntRz/Q= -github.com/openziti/foundation/v2 v2.0.24/go.mod h1:H0w/ldKyE0ynwpIwt68k2rhMwt874IVxPQcimMuHJ3s= -github.com/openziti/identity v1.0.54 h1:1O/i3hnm5oCuHlOXesx4+aC2bXeTGoT+Rg1l2xZF14Y= -github.com/openziti/identity v1.0.54/go.mod h1:ZhMiSF9okmA781kFl0m4BkeyAmf3XA20h1Dh1oz480I= +github.com/openziti/foundation/v2 v2.0.25 h1:tGb9wdu6KCpO49RJ3HX2ClOVHf8gdntplIh/7CEVaM4= +github.com/openziti/foundation/v2 v2.0.25/go.mod h1:EOqea8Q1wXd4hS9MxFYM6ngDgenKGxz8c+CJ8Svr7BI= +github.com/openziti/identity v1.0.55 h1:WwZhFyIfor27MafmfSPr/xsQoSqT3KOnIeqy3FC+n4w= +github.com/openziti/identity v1.0.55/go.mod h1:ZaB62FkLGPglM7cR/o2jRIDF6Apa1swNLad9NQ2sa7Q= github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc= github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ= -github.com/openziti/metrics v1.2.25 h1:acD/J/DcWgfbhmKS/s3HDvpt/1WS3QBZPeeGBZHbj94= -github.com/openziti/metrics v1.2.25/go.mod h1:s2r1FS+wUdJ3LXp1qJK6777iQ8gPWXE2HFfDsiJo1/Y= +github.com/openziti/metrics v1.2.26 h1:8q93bK1MYAdR9ODr0qNAJ1/BQpFtHYdxZiH0Fc9LLo8= +github.com/openziti/metrics v1.2.26/go.mod h1:Z1c9pNHQr+yZODDsOeim93rYg5Hw1kPsuHi3zdy70dA= github.com/openziti/runzmd v1.0.24 h1:jSwfqpA6SLCtpDUzdQl92gECc08itE8eFeHYdaJu4tY= github.com/openziti/runzmd v1.0.24/go.mod h1:NX3EPWMDZPIPNUztDOkLrV6akqdC/P/X0UUeAL63V58= -github.com/openziti/sdk-golang v0.20.51 h1:oVqo9kyh8OKtAAX4yrJIJa5nn6qZDvpfUqOlBPnqb14= -github.com/openziti/sdk-golang v0.20.51/go.mod h1:Ecgf8vgPSLOP7EgQgb3juv2UwsKbu37G1NHSqioTUCs= +github.com/openziti/sdk-golang v0.20.54 h1:c2PS+xOcCoDki5vAiCki4Zb0y6MddNZK2JuvmzL3Dbk= +github.com/openziti/sdk-golang v0.20.54/go.mod h1:xvjqDrrxy75g7y59MvKtzNbCzYbm1mpn3r91wsftmD4= github.com/openziti/secretstream v0.1.8 h1:AgPHLDuXTiM1apHQmBvwvSW1vbQqAm7wUJDHqkQ/6Nk= github.com/openziti/secretstream v0.1.8/go.mod h1:qcF8EmSX5SAT8k2pzsDI4bWugopv9AA+ltgWDrcAAEw= -github.com/openziti/storage v0.2.6 h1:/pbIRzDwrczMWRVkN75PfwAXFbArplIqhpRsUrsUOBc= -github.com/openziti/storage v0.2.6/go.mod h1:JnjCofrnPcajwn6VIB2CgI7pVVUFBL7evbezIsQ4AgA= -github.com/openziti/transport/v2 v2.0.88 h1:K2kIrDInbjFqXvzPg+EkyYZkUiy8rEkBnYRKshELuho= -github.com/openziti/transport/v2 v2.0.88/go.mod h1:1eh1lpeIvB3KgyEC+OykpLa8Dj2AUC5921iOd2ovkwE= +github.com/openziti/storage v0.2.7 h1:rQVVclnkCZyr4XXKMypIJf46HFGJX5KEYWEycUhWvtg= +github.com/openziti/storage v0.2.7/go.mod h1:bGhUs/0XDsEJnTtNTpFAIh1X4lfdKvHu0m+8Z1TFVyM= +github.com/openziti/transport/v2 v2.0.89 h1:XVggCrKAxFkNwW9/GLBZeqCDRWB+3T2jejPcK25W3+Q= +github.com/openziti/transport/v2 v2.0.89/go.mod h1:6JnNL8jsVBBDgphHHquPEl5aUsim2HYYE0Li5fzZqEQ= github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0= github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE= github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU= @@ -933,8 +933,8 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= diff --git a/network-tests/utils/ziti-echo/main.go b/network-tests/utils/ziti-echo/main.go deleted file mode 100644 index b549b7ff6..000000000 --- a/network-tests/utils/ziti-echo/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/openziti/ziti/network-tests/utils/ziti-echo/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/network-tests/ami/README.md b/zititest/ami/README.md similarity index 100% rename from network-tests/ami/README.md rename to zititest/ami/README.md diff --git a/network-tests/ami/cleanup-old-images.sh b/zititest/ami/cleanup-old-images.sh similarity index 100% rename from network-tests/ami/cleanup-old-images.sh rename to zititest/ami/cleanup-old-images.sh diff --git a/network-tests/ami/etc/apt/apt.conf.d/99remote-not-fancy b/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy similarity index 100% rename from network-tests/ami/etc/apt/apt.conf.d/99remote-not-fancy rename to zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy diff --git a/network-tests/ami/etc/sysctl.d/51-network-tuning.conf b/zititest/ami/etc/sysctl.d/51-network-tuning.conf similarity index 100% rename from network-tests/ami/etc/sysctl.d/51-network-tuning.conf rename to zititest/ami/etc/sysctl.d/51-network-tuning.conf diff --git a/network-tests/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf b/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf similarity index 100% rename from network-tests/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf rename to zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf diff --git a/network-tests/ami/list-images.sh b/zititest/ami/list-images.sh similarity index 100% rename from network-tests/ami/list-images.sh rename to zititest/ami/list-images.sh diff --git a/network-tests/ami/ziti-ami.pkr.hcl b/zititest/ami/ziti-ami.pkr.hcl similarity index 100% rename from network-tests/ami/ziti-ami.pkr.hcl rename to zititest/ami/ziti-ami.pkr.hcl diff --git a/network-tests/go.mod b/zititest/go.mod similarity index 77% rename from network-tests/go.mod rename to zititest/go.mod index e4acc2949..ac065d7c6 100644 --- a/network-tests/go.mod +++ b/zititest/go.mod @@ -1,23 +1,35 @@ -module github.com/openziti/ziti/network-tests +module github.com/openziti/ziti/zititest -go 1.19 +go 1.20 + +replace github.com/openziti/ziti => ../ require ( + github.com/Jeffail/gabs v1.4.0 + github.com/Jeffail/gabs/v2 v2.7.0 github.com/michaelquigley/pfxlog v0.6.10 - github.com/openziti/edge v0.24.239 + github.com/openziti/channel/v2 v2.0.79 + github.com/openziti/edge v0.24.313 github.com/openziti/fablab v0.4.52 - github.com/openziti/sdk-golang v0.18.76 - github.com/openziti/zitilab v0.1.60 + github.com/openziti/fabric v0.23.29 + github.com/openziti/foundation/v2 v2.0.25 + github.com/openziti/identity v1.0.55 + github.com/openziti/sdk-golang v0.20.54 + github.com/openziti/storage v0.2.7 + github.com/openziti/transport/v2 v2.0.89 + github.com/openziti/ziti v0.28.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.2 github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 + go.etcd.io/bbolt v1.3.7 + golang.org/x/net v0.10.0 + google.golang.org/protobuf v1.30.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/AppsFlyer/go-sundheit v0.5.0 // indirect - github.com/Jeffail/gabs v1.4.0 // indirect - github.com/Jeffail/gabs/v2 v2.7.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/MichaelMure/go-term-markdown v0.1.4 // indirect github.com/MichaelMure/go-term-text v0.3.1 // indirect @@ -31,13 +43,13 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/boltdb/bolt v1.3.1 // indirect github.com/c-bata/go-prompt v0.2.6 // indirect - github.com/cenkalti/backoff/v4 v4.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/coreos/go-iptables v0.6.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 // indirect github.com/dineshappavoo/basex v0.0.0-20170425072625-481a6f6dc663 // indirect github.com/disintegration/imaging v1.6.2 // indirect - github.com/dlclark/regexp2 v1.9.0 // indirect + github.com/dlclark/regexp2 v1.10.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/ef-ds/deque v1.0.4 // indirect github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 // indirect @@ -55,8 +67,8 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/runtime v0.25.0 // indirect - github.com/go-openapi/spec v0.20.8 // indirect + github.com/go-openapi/runtime v0.26.0 // indirect + github.com/go-openapi/spec v0.20.9 // indirect github.com/go-openapi/strfmt v0.21.7 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/go-openapi/validate v0.22.1 // indirect @@ -68,6 +80,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -75,18 +88,19 @@ require ( github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/raft v1.4.0 // indirect + github.com/hashicorp/raft v1.5.0 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d // indirect github.com/jedib0t/go-pretty/v6 v6.4.6 // indirect github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/josharian/native v1.0.0 // indirect + github.com/josharian/native v1.1.0 // indirect github.com/kataras/go-events v0.0.3 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 // indirect + github.com/klauspost/compress v1.16.5 // indirect github.com/kr/fs v0.1.0 // indirect github.com/kyokomi/emoji/v2 v2.2.12 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect @@ -95,37 +109,30 @@ require ( github.com/magiconair/properties v1.8.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-tty v0.0.3 // indirect - github.com/mdlayher/netlink v1.7.1 // indirect - github.com/mdlayher/socket v0.4.0 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/michaelquigley/figlet v0.0.0-20191015203154-054d06db54b4 // indirect - github.com/miekg/dns v1.1.53 // indirect + github.com/miekg/dns v1.1.54 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce // indirect - github.com/netfoundry/secretstream v0.1.5 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/openziti/agent v1.0.10 // indirect - github.com/openziti/channel/v2 v2.0.58 // indirect - github.com/openziti/edge-api v0.25.11 // indirect - github.com/openziti/fabric v0.22.87 // indirect - github.com/openziti/foundation/v2 v2.0.24 // indirect - github.com/openziti/identity v1.0.45 // indirect + github.com/openziti/agent v1.0.13 // indirect + github.com/openziti/edge-api v0.25.24 // indirect github.com/openziti/jwks v1.0.3 // indirect - github.com/openziti/metrics v1.2.19 // indirect - github.com/openziti/runzmd v1.0.20 // indirect - github.com/openziti/storage v0.1.49 // indirect - github.com/openziti/transport/v2 v2.0.72 // indirect + github.com/openziti/metrics v1.2.26 // indirect + github.com/openziti/runzmd v1.0.24 // indirect + github.com/openziti/secretstream v0.1.8 // indirect github.com/openziti/x509-claims v1.0.3 // indirect github.com/openziti/xweb/v2 v2.0.2 // indirect - github.com/openziti/ziti v0.27.9 // indirect github.com/openziti/ziti-db-explorer v1.1.1 // indirect github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect @@ -134,12 +141,13 @@ require ( github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect + github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rodaine/table v1.0.1 // indirect github.com/russross/blackfriday v1.5.2 // indirect - github.com/shirou/gopsutil/v3 v3.23.3 // indirect - github.com/shoenig/go-m1cpu v0.1.5 // indirect + github.com/shirou/gopsutil/v3 v3.23.4 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/speps/go-hashids v2.0.0+incompatible // indirect github.com/spf13/afero v1.6.0 // indirect @@ -156,28 +164,26 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.etcd.io/bbolt v1.3.7 // indirect - go.mongodb.org/mongo-driver v1.11.4 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.mongodb.org/mongo-driver v1.11.6 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect golang.org/x/crypto v0.9.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/image v0.7.0 // indirect golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/term v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect golang.org/x/tools v0.6.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect gopkg.in/AlecAivazis/survey.v1 v1.8.7 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect rsc.io/goversion v1.2.0 // indirect ) diff --git a/network-tests/go.sum b/zititest/go.sum similarity index 93% rename from network-tests/go.sum rename to zititest/go.sum index 45a9d74a8..40001183f 100644 --- a/network-tests/go.sum +++ b/zititest/go.sum @@ -122,8 +122,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= -github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -161,8 +161,8 @@ github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1 github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.9.0 h1:pTK/l/3qYIKaRXuHnEnIf7Y5NxfRPfpb7dis6/gdlVI= -github.com/dlclark/regexp2 v1.9.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= +github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -200,6 +200,10 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-acme/lego/v4 v4.2.0 h1:zEvpcDLqvzOlNUGBMA0MCKPpb9UBbnBzgWwCIbTEt2g= github.com/go-acme/lego/v4 v4.2.0/go.mod h1:jmhqxBaangB8txXZKjRLTPXFXUwPCTU2fU8S9/eQzBI= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -237,12 +241,12 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.25.0 h1:7yQTCdRbWhX8vnIjdzU8S00tBYf7Sg71EBeorlPHvhc= -github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs= +github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc= +github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= -github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= @@ -255,6 +259,13 @@ github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= @@ -284,6 +295,12 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -376,6 +393,9 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -418,8 +438,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.4.0 h1:tn28S/AWv0BtRQgwZv/1NELu8sCvI0FixqL8C8MYKeY= -github.com/hashicorp/raft v1.4.0/go.mod h1:nz64BIjXphDLATfKGG5RzHtNUPioLeKFsXEm88yTVew= +github.com/hashicorp/raft v1.5.0 h1:uNs9EfJ4FwiArZRxxfd/dQ5d33nV31/CdCHArH89hT8= +github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 h1:CO8dBMLH6dvE1jTn/30ZZw3iuPsNfajshWoJTnVc5cc= github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= @@ -432,6 +452,8 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1Rjl9Jw= github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= @@ -447,13 +469,14 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= -github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -464,11 +487,12 @@ github.com/kataras/go-events v0.0.3 h1:o5YK53uURXtrlg7qE/vovxd/yKOJcLuFtPQbf1rYM github.com/kataras/go-events v0.0.3/go.mod h1:bFBgtzwwzrag7kQmGuU1ZaVxhK2qseYPQomXoVEMsj4= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 h1:WjT3fLi9n8YWh/Ih8Q1LHAPsTqGddPcHqscN+PJ3i68= -github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= 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/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -489,6 +513,8 @@ github.com/kyokomi/emoji/v2 v2.2.12 h1:sSVA5nH9ebR3Zji1o31wu3yOwD1zKXQA2z0zUyeit github.com/kyokomi/emoji/v2 v2.2.12/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/linode/linodego v0.21.0/go.mod h1:UTpq1JUZD0CZsJ8rt+0CRkqbzrp1MbGakVPt2DXY5Mk= github.com/liquidweb/liquidweb-go v1.6.1/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= @@ -526,8 +552,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -540,10 +566,10 @@ github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4f github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdlayher/netlink v1.7.1 h1:FdUaT/e33HjEXagwELR8R3/KL1Fq5x3G5jgHLp/BTmg= -github.com/mdlayher/netlink v1.7.1/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ= -github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= -github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -553,8 +579,8 @@ github.com/michaelquigley/pfxlog v0.6.10 h1:IbC/H3MmSDcPlQHF1UZPQU13Dkrs0+ycWRyQ github.com/michaelquigley/pfxlog v0.6.10/go.mod h1:gEiNTfKEX6cJHSwRpOuqBpc8oYrlhMiDK/xMk/gV7D0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= -github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= +github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -573,9 +599,11 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= @@ -584,8 +612,6 @@ github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6Yf github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce h1:TqjP/BTDrwN7zP9xyXVuLsMBXYMt6LLYi55PlrIcq8U= github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/netfoundry/secretstream v0.1.5 h1:iQ4brqUeZO7xNlSpwZDhekPW8d5LlRyHwvvevBOP1IM= -github.com/netfoundry/secretstream v0.1.5/go.mod h1:N6Mvl9Lk8xs84hFS9qZfjcJWiXmpzqaXW/L9W0JYfXY= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nrdcg/auroradns v1.0.1/go.mod h1:y4pc0i9QXYlFCWrhWrUSIETnZgrf4KuwjDIWmmXo3JI= github.com/nrdcg/desec v0.5.0/go.mod h1:2ejvMazkav1VdDbv2HeQO7w+Ta1CGHqzQr27ZBYTuEQ= @@ -612,44 +638,42 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openziti/agent v1.0.10 h1:9oTmNXghlggD+O7BJdBp3PkD5kAZ1ssSC6IHZkMakzQ= -github.com/openziti/agent v1.0.10/go.mod h1:6APWgkPP6Uxf1/VyirdTVLAJxwam2vVyakrVw6yvs40= -github.com/openziti/channel/v2 v2.0.58 h1:j9baDM8nEAgHNhJ9n1h+WWbFSgCQCjvNB3KCr5x5q6c= -github.com/openziti/channel/v2 v2.0.58/go.mod h1:Wa3TS5o4pBFSGnDb9zRCGww29ZVXk0GnupwNpb/2DWE= -github.com/openziti/edge v0.24.239 h1:S7bAy/BfpGpKwXnfWuGgWpfjUEuJ5iwZojTxu9W8DO0= -github.com/openziti/edge v0.24.239/go.mod h1:G6PLbcyib36KH9hN6tMacr2UMin15EmZioSGPPptJ0U= -github.com/openziti/edge-api v0.25.11 h1:HHjDgoybPZGRZ+tM2udehI+U5Xv991iGED8E6CtDb9w= -github.com/openziti/edge-api v0.25.11/go.mod h1:PBFMYELgr7JUuaCqHobq1U+WESsutzgEDoELU/9qFOg= +github.com/openziti/agent v1.0.13 h1:RptJCEANPb904cDqlP7IYfBI+he8EyosimYhG7bp9D0= +github.com/openziti/agent v1.0.13/go.mod h1:CRbwhhnpsoDw0BxZsCRyQUozoRnGzH7+wuQVp1h4qX8= +github.com/openziti/channel/v2 v2.0.79 h1:pjbMmllLu1K3RzvX3K+FJK09bewrL5ZJGEL2cZiPmuM= +github.com/openziti/channel/v2 v2.0.79/go.mod h1:NOwAKC9nTZi41njN/4iRNWpGpt4psu5jjhv8bA9FbwE= +github.com/openziti/edge v0.24.313 h1:r8Foxel03S4c9mlkbS5cSS0DxSVjEzpLkkX1nkvI+4Q= +github.com/openziti/edge v0.24.313/go.mod h1:5gH8JPtRYO867mhEPwWBqNqYnZXFIGDvmymn180nhKM= +github.com/openziti/edge-api v0.25.24 h1:XrF3AtF9mnJXgG7rSV2M50Dj/EKUkBUaDdb9/n2TDHI= +github.com/openziti/edge-api v0.25.24/go.mod h1:rmEkj8jAkBTUhhgE/GFXije6bpFbd2P9TzdxTqZlXI8= github.com/openziti/fablab v0.4.52 h1:X5+NaRnfPxbzhxUh9b4IQmVNVgYWFf8/Ck2sKNz77ho= github.com/openziti/fablab v0.4.52/go.mod h1:aF8Fu3C8hnnaOJyAZz3AXGY4cMxQyBLhoIlSRJ/VVpc= -github.com/openziti/fabric v0.22.87 h1:Vc71NOFGLQapr8YZjx4p+f9+HHKm63o4kpt4LMjXTY4= -github.com/openziti/fabric v0.22.87/go.mod h1:w/cleYmpE/coUjjCzoRbpO648QWwSee0V4H8mfyqCdg= -github.com/openziti/foundation/v2 v2.0.24 h1:cNJCbh4o9E+7mtSUDo7ZBuMoPjJAilDWgr7X8ntRz/Q= -github.com/openziti/foundation/v2 v2.0.24/go.mod h1:H0w/ldKyE0ynwpIwt68k2rhMwt874IVxPQcimMuHJ3s= -github.com/openziti/identity v1.0.45 h1:e2kXoMCPcaUXy+k6GwasuKeGSJwavFEr+eOvUA228UY= -github.com/openziti/identity v1.0.45/go.mod h1:fQ5bjNu4L1Yqk011xNB1QXvsmBRHnm5d498fi1bhl24= +github.com/openziti/fabric v0.23.29 h1:FbAeUhfkNGYPNCYo3BFzRByvMTKhscxJEQxYU0BJJdA= +github.com/openziti/fabric v0.23.29/go.mod h1:/M8URo+qloi39qG0QWvXTgtpiPPneNYOjR+VvywS0cw= +github.com/openziti/foundation/v2 v2.0.25 h1:tGb9wdu6KCpO49RJ3HX2ClOVHf8gdntplIh/7CEVaM4= +github.com/openziti/foundation/v2 v2.0.25/go.mod h1:EOqea8Q1wXd4hS9MxFYM6ngDgenKGxz8c+CJ8Svr7BI= +github.com/openziti/identity v1.0.55 h1:WwZhFyIfor27MafmfSPr/xsQoSqT3KOnIeqy3FC+n4w= +github.com/openziti/identity v1.0.55/go.mod h1:ZaB62FkLGPglM7cR/o2jRIDF6Apa1swNLad9NQ2sa7Q= github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc= github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ= -github.com/openziti/metrics v1.2.19 h1:gQO3e2lUotRHBdGUXYBPWMIErIyyF5hw0EakwQbJzuM= -github.com/openziti/metrics v1.2.19/go.mod h1:ovvxTpDBxGLcVLHgPTFFvwT4ur8p4Z76BPUhIE5iwqc= -github.com/openziti/runzmd v1.0.20 h1:LzRPZRVO9AepAFzGTEsRGp2LRVtJp5vr+QOBl8KbN4w= -github.com/openziti/runzmd v1.0.20/go.mod h1:IXTk5dHAZxtqjg9WVHOiyXHqEHZdwaH5Wg80h5Ux3bQ= -github.com/openziti/sdk-golang v0.18.76 h1:D+UW1lpGHBBgfVrObpauq9RvJV/TFPdEEshfuPkiMcI= -github.com/openziti/sdk-golang v0.18.76/go.mod h1:kw/5rWDLwx52iwW/4a0VRQMUi7GPSI3aETx+G5TvdFQ= -github.com/openziti/storage v0.1.49 h1:luRsssYlGhpiJxjgc+FWF/yd2JLs9IKfeKID/5Hknrg= -github.com/openziti/storage v0.1.49/go.mod h1:Le2VFNL67YewLtaCnGNXPLH18Yrh/EMxeJ/eXxTOwak= -github.com/openziti/transport/v2 v2.0.72 h1:yjJtxy3Ckx5I4pDicmxILTdqQB6D18LSg2Zvsde0T00= -github.com/openziti/transport/v2 v2.0.72/go.mod h1:YuDvm+syZc9nfdhbdPZdtuL1Dfw+bELWhWVYAg73ups= +github.com/openziti/metrics v1.2.26 h1:8q93bK1MYAdR9ODr0qNAJ1/BQpFtHYdxZiH0Fc9LLo8= +github.com/openziti/metrics v1.2.26/go.mod h1:Z1c9pNHQr+yZODDsOeim93rYg5Hw1kPsuHi3zdy70dA= +github.com/openziti/runzmd v1.0.24 h1:jSwfqpA6SLCtpDUzdQl92gECc08itE8eFeHYdaJu4tY= +github.com/openziti/runzmd v1.0.24/go.mod h1:NX3EPWMDZPIPNUztDOkLrV6akqdC/P/X0UUeAL63V58= +github.com/openziti/sdk-golang v0.20.54 h1:c2PS+xOcCoDki5vAiCki4Zb0y6MddNZK2JuvmzL3Dbk= +github.com/openziti/sdk-golang v0.20.54/go.mod h1:xvjqDrrxy75g7y59MvKtzNbCzYbm1mpn3r91wsftmD4= +github.com/openziti/secretstream v0.1.8 h1:AgPHLDuXTiM1apHQmBvwvSW1vbQqAm7wUJDHqkQ/6Nk= +github.com/openziti/secretstream v0.1.8/go.mod h1:qcF8EmSX5SAT8k2pzsDI4bWugopv9AA+ltgWDrcAAEw= +github.com/openziti/storage v0.2.7 h1:rQVVclnkCZyr4XXKMypIJf46HFGJX5KEYWEycUhWvtg= +github.com/openziti/storage v0.2.7/go.mod h1:bGhUs/0XDsEJnTtNTpFAIh1X4lfdKvHu0m+8Z1TFVyM= +github.com/openziti/transport/v2 v2.0.89 h1:XVggCrKAxFkNwW9/GLBZeqCDRWB+3T2jejPcK25W3+Q= +github.com/openziti/transport/v2 v2.0.89/go.mod h1:6JnNL8jsVBBDgphHHquPEl5aUsim2HYYE0Li5fzZqEQ= github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0= github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE= github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU= github.com/openziti/xweb/v2 v2.0.2/go.mod h1:KQOOlnJk08EZT3TWkvDj/pbIUEVbgG0IrrNzl8gsi40= -github.com/openziti/ziti v0.27.9 h1:GsPqGFpHLLrvx4G+nXs7gKDyeSwl46D4GOLNFBmNI9c= -github.com/openziti/ziti v0.27.9/go.mod h1:tSF7cciowQXna3O++xyUSq2S7hPZwYnH+WUwSr2NNsA= github.com/openziti/ziti-db-explorer v1.1.1 h1:G0eoTby+aIjjt5TxEfR+FMI2CWd4RvZFjzaIMX2lEBw= github.com/openziti/ziti-db-explorer v1.1.1/go.mod h1:h76h7Tsb+khb0v+CqYKL6ifUfJbUMjGBFU2IvupfBE4= -github.com/openziti/zitilab v0.1.60 h1:uyg/1KXA5+dhg3ibgPqqvxrTRP5YvplTaSHj2w4/3oQ= -github.com/openziti/zitilab v0.1.60/go.mod h1:lNk7ss0dpBnowHdd0LX7S688a+DKFQigX0FVhbcm5LY= github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c= github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM= @@ -704,6 +728,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA= +github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -727,13 +753,13 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= -github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= -github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= -github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= +github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= +github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= -github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -786,8 +812,8 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= @@ -801,6 +827,10 @@ github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -825,8 +855,9 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -835,8 +866,8 @@ go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsX go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas= -go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o= +go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -848,13 +879,17 @@ 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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= @@ -889,8 +924,8 @@ 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-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-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= 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-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1089,6 +1124,7 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1340,6 +1376,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w= rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= diff --git a/network-tests/ha/actions/bootstrap.go b/zititest/models/ha/actions/bootstrap.go similarity index 92% rename from network-tests/ha/actions/bootstrap.go rename to zititest/models/ha/actions/bootstrap.go index 0b853da87..4692c7cdb 100644 --- a/network-tests/ha/actions/bootstrap.go +++ b/zititest/models/ha/actions/bootstrap.go @@ -8,9 +8,9 @@ import ( "github.com/openziti/fablab/kernel/lib/actions/host" "github.com/openziti/fablab/kernel/lib/actions/semaphore" "github.com/openziti/fablab/kernel/model" - zitilib_actions "github.com/openziti/zitilab/actions" - "github.com/openziti/zitilab/actions/edge" - "github.com/openziti/zitilab/models" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" ) type bootstrapAction struct{} diff --git a/network-tests/ha/actions/start.go b/zititest/models/ha/actions/start.go similarity index 89% rename from network-tests/ha/actions/start.go rename to zititest/models/ha/actions/start.go index f1296986d..0b615c754 100644 --- a/network-tests/ha/actions/start.go +++ b/zititest/models/ha/actions/start.go @@ -7,9 +7,9 @@ import ( "github.com/openziti/fablab/kernel/lib/actions/component" "github.com/openziti/fablab/kernel/lib/actions/semaphore" "github.com/openziti/fablab/kernel/model" - util_actions "github.com/openziti/ziti/network-tests/utils/actions" - zitilib_actions "github.com/openziti/zitilab/actions" - "github.com/openziti/zitilab/models" + util_actions "github.com/openziti/ziti/zititest/utils/actions" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/models" ) func NewStartAction(metricbeat MetricbeatConfig, consul ConsulConfig) model.ActionBinder { diff --git a/network-tests/ha/configs/consul.hcl b/zititest/models/ha/configs/consul.hcl similarity index 100% rename from network-tests/ha/configs/consul.hcl rename to zititest/models/ha/configs/consul.hcl diff --git a/network-tests/ha/configs/ctrl.yml.tmpl b/zititest/models/ha/configs/ctrl.yml.tmpl similarity index 100% rename from network-tests/ha/configs/ctrl.yml.tmpl rename to zititest/models/ha/configs/ctrl.yml.tmpl diff --git a/network-tests/ha/configs/metricbeat.yml b/zititest/models/ha/configs/metricbeat.yml similarity index 100% rename from network-tests/ha/configs/metricbeat.yml rename to zititest/models/ha/configs/metricbeat.yml diff --git a/network-tests/ha/configs/router.yml.tmpl b/zititest/models/ha/configs/router.yml.tmpl similarity index 100% rename from network-tests/ha/configs/router.yml.tmpl rename to zititest/models/ha/configs/router.yml.tmpl diff --git a/network-tests/ha/configs/ziti.hcl b/zititest/models/ha/configs/ziti.hcl similarity index 100% rename from network-tests/ha/configs/ziti.hcl rename to zititest/models/ha/configs/ziti.hcl diff --git a/network-tests/ha/main.go b/zititest/models/ha/main.go similarity index 96% rename from network-tests/ha/main.go rename to zititest/models/ha/main.go index 3b78e4c8a..3212bc922 100644 --- a/network-tests/ha/main.go +++ b/zititest/models/ha/main.go @@ -33,11 +33,11 @@ import ( "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" "github.com/openziti/fablab/kernel/model" "github.com/openziti/fablab/resources" - "github.com/openziti/ziti/network-tests/ha/actions" - "github.com/openziti/ziti/network-tests/test_resources" - "github.com/openziti/zitilab" - "github.com/openziti/zitilab/actions/edge" - zitilib_runlevel_1_configuration "github.com/openziti/zitilab/runlevel/1_configuration" + "github.com/openziti/ziti/zititest/models/ha/actions" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + zitilib_runlevel_1_configuration "github.com/openziti/ziti/zititest/zitilab/runlevel/1_configuration" "github.com/sirupsen/logrus" "os" "time" diff --git a/network-tests/router-test/configs/ctrl.yml b/zititest/models/router-test/configs/ctrl.yml similarity index 100% rename from network-tests/router-test/configs/ctrl.yml rename to zititest/models/router-test/configs/ctrl.yml diff --git a/network-tests/router-test/configs/router.yml b/zititest/models/router-test/configs/router.yml similarity index 100% rename from network-tests/router-test/configs/router.yml rename to zititest/models/router-test/configs/router.yml diff --git a/network-tests/router-test/main.go b/zititest/models/router-test/main.go similarity index 94% rename from network-tests/router-test/main.go rename to zititest/models/router-test/main.go index 1e73bd7bb..33bba3da6 100644 --- a/network-tests/router-test/main.go +++ b/zititest/models/router-test/main.go @@ -22,11 +22,11 @@ import ( "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" "github.com/openziti/fablab/kernel/model" "github.com/openziti/fablab/resources" - "github.com/openziti/ziti/network-tests/test_resources" - "github.com/openziti/zitilab" - "github.com/openziti/zitilab/actions/edge" - "github.com/openziti/zitilab/models" - zitilib_runlevel_1_configuration "github.com/openziti/zitilab/runlevel/1_configuration" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" + zitilib_runlevel_1_configuration "github.com/openziti/ziti/zititest/zitilab/runlevel/1_configuration" "os" "path" "strings" diff --git a/network-tests/simple-transfer/main.go b/zititest/models/simple-transfer/main.go similarity index 93% rename from network-tests/simple-transfer/main.go rename to zititest/models/simple-transfer/main.go index 5c17bd8cc..658cee65c 100644 --- a/network-tests/simple-transfer/main.go +++ b/zititest/models/simple-transfer/main.go @@ -18,7 +18,7 @@ package main import ( "github.com/openziti/fablab" - "github.com/openziti/ziti/network-tests/simple" + "github.com/openziti/ziti/zititest/models/simple" ) func main() { diff --git a/network-tests/simple/actions/bootstrap.go b/zititest/models/simple/actions/bootstrap.go similarity index 74% rename from network-tests/simple/actions/bootstrap.go rename to zititest/models/simple/actions/bootstrap.go index 8f8afd2f1..b9c292483 100644 --- a/network-tests/simple/actions/bootstrap.go +++ b/zititest/models/simple/actions/bootstrap.go @@ -24,9 +24,9 @@ import ( "github.com/openziti/fablab/kernel/lib/actions/host" "github.com/openziti/fablab/kernel/lib/actions/semaphore" "github.com/openziti/fablab/kernel/model" - zitilib_actions "github.com/openziti/zitilab/actions" - "github.com/openziti/zitilab/actions/edge" - "github.com/openziti/zitilab/models" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" ) type bootstrapAction struct{} @@ -61,11 +61,11 @@ func (a *bootstrapAction) bind(m *model.Model) model.Action { workflow.AddAction(zitilib_actions.Edge("create", "service-edge-router-policy", "serp-all", "--service-roles", "#all", "--edge-router-roles", "#all")) - workflow.AddAction(zitilib_actions.Edge("create", "config", "files-host", "host.v2", ` + workflow.AddAction(zitilib_actions.Edge("create", "config", "files-host", "host.v1", ` { - "terminators" : [ - { "address" : "ziti-smoketest-files.s3-us-west-1.amazonaws.com", "port" : 443, "protocol" : "tcp" } - ] + "address" : "ziti-smoketest-files.s3-us-west-1.amazonaws.com", + "port" : 443, + "protocol" : "tcp" }`)) workflow.AddAction(zitilib_actions.Edge("create", "config", "files-intercept-ert-unencrypted", "intercept.v1", ` @@ -96,14 +96,32 @@ func (a *bootstrapAction) bind(m *model.Model) model.Action { "protocols": ["tcp"] }`)) + workflow.AddAction(zitilib_actions.Edge("create", "config", "files-intercept-ziti-tunnel-unencrypted", "intercept.v1", ` + { + "addresses": ["ziti-files-ziti-tunnel-unencrypted.s3-us-west-1.amazonaws.ziti"], + "portRanges" : [ { "low": 443, "high": 443 } ], + "protocols": ["tcp"] + }`)) + + workflow.AddAction(zitilib_actions.Edge("create", "config", "files-intercept-ziti-tunnel", "intercept.v1", ` + { + "addresses": ["ziti-files-ziti-tunnel.s3-us-west-1.amazonaws.ziti"], + "portRanges" : [ { "low": 443, "high": 443 } ], + "protocols": ["tcp"] + }`)) + workflow.AddAction(zitilib_actions.Edge("create", "service", "ert-files-unencrypted", "-c", "files-host,files-intercept-ert-unencrypted", "-e", "OFF", "-a", "ert")) workflow.AddAction(zitilib_actions.Edge("create", "service", "ert-files", "-c", "files-host,files-intercept-ert", "-a", "ert")) workflow.AddAction(zitilib_actions.Edge("create", "service", "zet-files-unencrypted", "-c", "files-host,files-intercept-zet-unencrypted", "-e", "OFF", "-a", "zet")) workflow.AddAction(zitilib_actions.Edge("create", "service", "zet-files", "-c", "files-host,files-intercept-zet", "-a", "zet")) + workflow.AddAction(zitilib_actions.Edge("create", "service", "ziti-tunnel-files-unencrypted", "-c", "files-host,files-intercept-ziti-tunnel-unencrypted", "-e", "OFF", "-a", "ziti-tunnel")) + workflow.AddAction(zitilib_actions.Edge("create", "service", "ziti-tunnel-files", "-c", "files-host,files-intercept-ziti-tunnel", "-a", "ziti-tunnel")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "ert-hosts", "Bind", "--service-roles", "#ert", "--identity-roles", "#ert-host")) workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "zet-hosts", "Bind", "--service-roles", "#zet", "--identity-roles", "#zet-host")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "ziti-tunnel-hosts", "Bind", "--service-roles", "#ziti-tunnel", "--identity-roles", "#ziti-tunnel-host")) workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "client-tunnelers", "Dial", "--service-roles", "#all", "--identity-roles", "#client")) workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "client-routers", "--edge-router-roles", "#client", "--identity-roles", "#client")) @@ -111,5 +129,16 @@ func (a *bootstrapAction) bind(m *model.Model) model.Action { workflow.AddAction(component.Stop(models.ControllerTag)) + workflow.AddAction(model.ActionFunc(func(m *model.Model) error { + cmds := []string{ + "sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf", + "sudo systemctl restart systemd-resolved", + } + + return m.ForEachComponent(".ziti-tunnel", 2, func(c *model.Component) error { + return host.Exec(c.GetHost(), cmds...).Execute(c.GetModel()) + }) + })) + return workflow } diff --git a/network-tests/simple/actions/start.go b/zititest/models/simple/actions/start.go similarity index 93% rename from network-tests/simple/actions/start.go rename to zititest/models/simple/actions/start.go index eb3aba464..b00060247 100644 --- a/network-tests/simple/actions/start.go +++ b/zititest/models/simple/actions/start.go @@ -25,9 +25,9 @@ import ( "github.com/openziti/fablab/kernel/lib/actions/component" "github.com/openziti/fablab/kernel/lib/actions/semaphore" "github.com/openziti/fablab/kernel/model" - util_actions "github.com/openziti/ziti/network-tests/utils/actions" - zitilib_actions "github.com/openziti/zitilab/actions" - "github.com/openziti/zitilab/models" + util_actions "github.com/openziti/ziti/zititest/utils/actions" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/models" ) func NewStartAction(metricbeat MetricbeatConfig, consul ConsulConfig) model.ActionBinder { diff --git a/network-tests/simple/configs/consul.hcl b/zititest/models/simple/configs/consul.hcl similarity index 100% rename from network-tests/simple/configs/consul.hcl rename to zititest/models/simple/configs/consul.hcl diff --git a/network-tests/simple/configs/ctrl.yml b/zititest/models/simple/configs/ctrl.yml similarity index 100% rename from network-tests/simple/configs/ctrl.yml rename to zititest/models/simple/configs/ctrl.yml diff --git a/network-tests/simple/configs/elasticsearch.repo b/zititest/models/simple/configs/elasticsearch.repo similarity index 100% rename from network-tests/simple/configs/elasticsearch.repo rename to zititest/models/simple/configs/elasticsearch.repo diff --git a/network-tests/simple/configs/metricbeat.yml b/zititest/models/simple/configs/metricbeat.yml similarity index 100% rename from network-tests/simple/configs/metricbeat.yml rename to zititest/models/simple/configs/metricbeat.yml diff --git a/network-tests/simple/configs/router.yml b/zititest/models/simple/configs/router.yml similarity index 100% rename from network-tests/simple/configs/router.yml rename to zititest/models/simple/configs/router.yml diff --git a/network-tests/simple/configs/ziti.hcl b/zititest/models/simple/configs/ziti.hcl similarity index 100% rename from network-tests/simple/configs/ziti.hcl rename to zititest/models/simple/configs/ziti.hcl diff --git a/network-tests/simple/simple.go b/zititest/models/simple/simple.go similarity index 86% rename from network-tests/simple/simple.go rename to zititest/models/simple/simple.go index 91a27688a..79ff69cf8 100644 --- a/network-tests/simple/simple.go +++ b/zititest/models/simple/simple.go @@ -32,12 +32,13 @@ import ( "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" "github.com/openziti/fablab/kernel/model" "github.com/openziti/fablab/resources" - actions2 "github.com/openziti/ziti/network-tests/simple/actions" - "github.com/openziti/ziti/network-tests/simple/stages/5_operation" - "github.com/openziti/ziti/network-tests/test_resources" - "github.com/openziti/zitilab" - "github.com/openziti/zitilab/actions/edge" - zitilib_runlevel_1_configuration "github.com/openziti/zitilab/runlevel/1_configuration" + actions2 "github.com/openziti/ziti/zititest/models/simple/actions" + "github.com/openziti/ziti/zititest/models/simple/stages/5_operation" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + zitilib_runlevel_1_configuration "github.com/openziti/ziti/zititest/zitilab/runlevel/1_configuration" + "github.com/openziti/ziti/zititest/zitilab/stageziti" "github.com/sirupsen/logrus" "os" "time" @@ -157,6 +158,21 @@ var Model = &model.Model{ }, }, }, + "ziti-tunnel-client": { + Scope: model.Scope{Tags: model.Tags{"ziti-tunnel-client"}}, + InstanceType: "t2.micro", + Components: model.Components{ + "ziti-tunnel-client": { + Scope: model.Scope{Tags: model.Tags{"ziti-tunnel", "sdk-app", "client"}}, + BinaryName: "ziti tunnel", + PublicIdentity: "ziti-tunnel-client", + RunWithSudo: true, + }, + "consul": { + BinaryName: "consul", + }, + }, + }, }, }, "us-west-2": { @@ -199,6 +215,20 @@ var Model = &model.Model{ }, }, }, + "ziti-tunnel-host": { + InstanceType: "t2.micro", + Components: model.Components{ + "ziti-tunnel-host": { + Scope: model.Scope{Tags: model.Tags{"ziti-tunnel", "sdk-app", "host", "ziti-tunnel-host"}}, + BinaryName: "ziti tunnel", + PublicIdentity: "ziti-tunnel-host", + RunWithSudo: true, + }, + "consul": { + BinaryName: "consul", + }, + }, + }, }, }, }, @@ -232,7 +262,7 @@ var Model = &model.Model{ ), config.Component(), devkit.DevKitF(zitilab.ZitiRoot, []string{"ziti", "ziti-echo"}), - //stageziti.FetchZitiEdgeTunnel("v0.21.4"), + stageziti.FetchZitiEdgeTunnel("v0.21.4"), }, Distribution: model.DistributionStages{ diff --git a/network-tests/simple/stages/5_operation/echo_client.go b/zititest/models/simple/stages/5_operation/echo_client.go similarity index 100% rename from network-tests/simple/stages/5_operation/echo_client.go rename to zititest/models/simple/stages/5_operation/echo_client.go diff --git a/network-tests/simple/stages/5_operation/echo_server.go b/zititest/models/simple/stages/5_operation/echo_server.go similarity index 100% rename from network-tests/simple/stages/5_operation/echo_server.go rename to zititest/models/simple/stages/5_operation/echo_server.go diff --git a/zititest/models/smart/actions.go b/zititest/models/smart/actions.go new file mode 100644 index 000000000..3f9f146af --- /dev/null +++ b/zititest/models/smart/actions.go @@ -0,0 +1,41 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/models/smart/actions" + zitilab_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/console" +) + +func newActionsFactory() model.Factory { + return &actionsFactory{} +} + +func (_ *actionsFactory) Build(m *model.Model) error { + m.Actions = model.ActionBinders{ + "bootstrap": actions.NewBootstrapAction(), + "start": actions.NewStartAction(), + "stop": actions.NewStopAction(), + "console": func(m *model.Model) model.Action { return console.Console() }, + "logs": func(m *model.Model) model.Action { return zitilab_actions.Logs() }, + } + return nil +} + +type actionsFactory struct{} diff --git a/zititest/models/smart/actions/bootstrap.go b/zititest/models/smart/actions/bootstrap.go new file mode 100644 index 000000000..e4f99f3d2 --- /dev/null +++ b/zititest/models/smart/actions/bootstrap.go @@ -0,0 +1,91 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "fmt" + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/models" + "github.com/sirupsen/logrus" + "path/filepath" + "time" +) + +func NewBootstrapAction() model.ActionBinder { + action := &bootstrapAction{} + return action.bind +} + +func (self *bootstrapAction) bind(m *model.Model) model.Action { + workflow := actions.Workflow() + + workflow.AddAction(component.Stop(models.ControllerTag)) + workflow.AddAction(host.Exec(m.MustSelectHost(models.HasControllerComponent), "rm -f ~/ctrl.db")) + workflow.AddAction(component.Start(models.ControllerTag)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + for _, router := range m.SelectComponents(models.RouterTag) { + cert := fmt.Sprintf("/intermediate/certs/%s-client.cert", router.PublicIdentity) + workflow.AddAction(zitilib_actions.Fabric("create", "router", filepath.Join(model.PkiBuild(), cert))) + } + + serviceActions, err := self.createServiceActions(m) + if err != nil { + logrus.Fatalf("error creating service actions (%v)", err) + } + for _, serviceAction := range serviceActions { + workflow.AddAction(serviceAction) + } + + sshUsername := m.MustStringVariable("credentials.ssh.username") + for _, h := range m.SelectHosts("*") { + workflow.AddAction(host.Exec(h, fmt.Sprintf("mkdir -p /home/%s/.ziti", sshUsername))) + workflow.AddAction(host.Exec(h, fmt.Sprintf("rm -f /home/%s/.ziti/identities.yml", sshUsername))) + workflow.AddAction(host.Exec(h, fmt.Sprintf("ln -s /home/%s/fablab/cfg/remote_identities.yml /home/%s/.ziti/identities.yml", sshUsername, sshUsername))) + } + + workflow.AddAction(component.Stop(models.ControllerTag)) + + return workflow +} + +func (_ *bootstrapAction) createServiceActions(m *model.Model) ([]model.Action, error) { + var serviceActions []model.Action + hosts, err := m.MustSelectHosts(models.LoopListenerTag, 1) + if err != nil { + return nil, err + } + + router, err := m.SelectComponent(".router.terminator") + if err != nil { + return nil, err + } + + for _, h := range hosts { + serviceActions = append(serviceActions, zitilib_actions.Fabric("create", "service", h.GetId())) + serviceActions = append(serviceActions, zitilib_actions.Fabric("create", "terminator", h.GetId(), router.PublicIdentity, "tcp:"+h.PrivateIp+":8171")) + } + + return serviceActions, nil +} + +type bootstrapAction struct{} diff --git a/zititest/models/smart/actions/start.go b/zititest/models/smart/actions/start.go new file mode 100644 index 000000000..ab7a41f1f --- /dev/null +++ b/zititest/models/smart/actions/start.go @@ -0,0 +1,42 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/models" + "time" +) + +func NewStartAction() model.ActionBinder { + action := startAction{} + return action.bind +} + +func (self *startAction) bind(*model.Model) model.Action { + workflow := actions.Workflow() + workflow.AddAction(component.Start(models.ControllerTag)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + workflow.AddAction(component.Start(models.RouterTag)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + return workflow +} + +type startAction struct{} diff --git a/zititest/models/smart/actions/stop.go b/zititest/models/smart/actions/stop.go new file mode 100644 index 000000000..841bbc28a --- /dev/null +++ b/zititest/models/smart/actions/stop.go @@ -0,0 +1,41 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/models" +) + +func NewStopAction() model.ActionBinder { + action := &stopAction{} + return action.bind +} + +func (_ *stopAction) bind(m *model.Model) model.Action { + return actions.Workflow( + host.GroupKill(models.LoopDialerTag, "ziti-fabric-test"), + host.GroupKill(models.LoopListenerTag, "ziti-fabric-test"), + component.Stop(models.RouterTag), + component.Stop(models.ControllerTag), + ) +} + +type stopAction struct{} diff --git a/zititest/models/smart/config/10-ambient.loop2.yml b/zititest/models/smart/config/10-ambient.loop2.yml new file mode 100644 index 000000000..b4c24193f --- /dev/null +++ b/zititest/models/smart/config/10-ambient.loop2.yml @@ -0,0 +1,30 @@ +# This is an example workloads definition for the loop2 tool. +# +workloads: + - name: chatter + concurrency: 10 + dialer: + txRequests: 100 + txPacing: 500 + txMaxJitter: 500 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 8192 + listener: + txRequests: 100 + txPacing: 500 + txMaxJitter: 500 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 8192 + + - name: big + concurrency: 1 + dialer: + txRequests: 20 + txPacing: 1000 + txMaxJitter: 2500 + payloadMinBytes: 51200000 + payloadMaxBytes: 102400000 + listener: + rxTimeout: 30000 diff --git a/zititest/models/smart/config/4k-chatter.loop2.yml b/zititest/models/smart/config/4k-chatter.loop2.yml new file mode 100644 index 000000000..ae66100c6 --- /dev/null +++ b/zititest/models/smart/config/4k-chatter.loop2.yml @@ -0,0 +1,17 @@ +workloads: + - name: chatter + concurrency: 4096 + dialer: + txRequests: 2000000 + txPacing: 30000 + txMaxJitter: 10000 + rxTimeout: 240000 + payloadMinBytes: 64 + payloadMaxBytes: 256 + listener: + txRequests: 2000000 + txPacing: 30000 + txMaxJitter: 10000 + rxTimeout: 240000 + payloadMinBytes: 64 + payloadMaxBytes: 256 \ No newline at end of file diff --git a/zititest/models/smart/config/ctrl.yml b/zititest/models/smart/config/ctrl.yml new file mode 100644 index 000000000..2f0c7150e --- /dev/null +++ b/zititest/models/smart/config/ctrl.yml @@ -0,0 +1,24 @@ +v: 3 + +db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/ctrl.db + +identity: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-client.cert + server_cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-server.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/keys/{{ .Component.PublicIdentity }}.key + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-server.chain.pem + +# Disable smart routing for zitilib/characterization transit-less configuration +# +network: + cycleSeconds: 120 + smart: + rerouteFraction: 0 + rerouteCap: 0 +# # + +ctrl: + listener: tls:0.0.0.0:6262 + +mgmt: + listener: tls:0.0.0.0:10000 diff --git a/zititest/models/smart/config/egress_router.yml b/zititest/models/smart/config/egress_router.yml new file mode 100644 index 000000000..b965f8bb3 --- /dev/null +++ b/zititest/models/smart/config/egress_router.yml @@ -0,0 +1,30 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.PublicIdentity}} +{{$protocol := .Model.MustVariable "zitilib.fabric.data_plane_protocol"}} +{{$ctrl_ip := publicIp "component.ctrl"}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +forwarder: + latencyProbeInterval: 1000 + +identity: + cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/pki/intermediate/keys/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.chain.pem + +ctrl: + endpoint: tls:{{$ctrl_ip}}:6262 + +dialers: + - binding: transport + +link: + listeners: + - binding: transport + bind: {{$protocol}}:0.0.0.0:6000 + advertise: {{$protocol}}:{{$router_ip}}:6000 + dialers: + - binding: transport diff --git a/zititest/models/smart/config/ingress_router.yml b/zititest/models/smart/config/ingress_router.yml new file mode 100644 index 000000000..abbabd48f --- /dev/null +++ b/zititest/models/smart/config/ingress_router.yml @@ -0,0 +1,42 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.PublicIdentity}} +{{$protocol := .Model.MustVariable "zitilib.fabric.data_plane_protocol"}} +{{$ctrl_ip := publicIp "component.ctrl"}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +forwarder: + latencyProbeInterval: 1000 + +identity: + cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/pki/intermediate/keys/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.chain.pem + +ctrl: + endpoint: tls:{{$ctrl_ip}}:6262 + +listeners: + - binding: proxy + address: tcp:0.0.0.0:7001 + service: iperf + + - binding: proxy_udp + address: udp:0.0.0.0:7001 + service: iperf_udp + + - binding: transport + address: tls:0.0.0.0:7002 + +dialers: + - binding: transport + +link: + listeners: + - binding: transport + bind: {{$protocol}}:0.0.0.0:6000 + advertise: {{$protocol}}:{{$router_ip}}:6000 + dialers: + - binding: transport diff --git a/zititest/models/smart/config/remote_identities.yml b/zititest/models/smart/config/remote_identities.yml new file mode 100644 index 000000000..2f280a03f --- /dev/null +++ b/zititest/models/smart/config/remote_identities.yml @@ -0,0 +1,5 @@ +default: + endpoint: tls:{{ publicIp "component.ctrl" }}:10000 + cert: /home/ubuntu/fablab/pki/intermediate/certs/dotziti-client.cert + key: /home/ubuntu/fablab/pki/intermediate/keys/dotziti.key + caCert: /home/ubuntu/fablab/pki/intermediate/certs/dotziti-server.chain.pem diff --git a/zititest/models/smart/config/transit_router.yml b/zititest/models/smart/config/transit_router.yml new file mode 100644 index 000000000..a291f9aff --- /dev/null +++ b/zititest/models/smart/config/transit_router.yml @@ -0,0 +1,27 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.PublicIdentity}} +{{$protocol := .Model.MustVariable "zitilib.fabric.data_plane_protocol"}} +{{$ctrl_ip := publicIp "component.ctrl"}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +forwarder: + latencyProbeInterval: 1000 + +identity: + cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/pki/intermediate/keys/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.chain.pem + +ctrl: + endpoint: tls:{{$ctrl_ip}}:6262 + +link: + listeners: + - binding: transport + bind: {{$protocol}}:0.0.0.0:6000 + advertise: {{$protocol}}:{{$router_ip}}:6000 + dialers: + - binding: transport diff --git a/zititest/models/smart/hosts.go b/zititest/models/smart/hosts.go new file mode 100644 index 000000000..129fa2f16 --- /dev/null +++ b/zititest/models/smart/hosts.go @@ -0,0 +1,63 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import "github.com/openziti/fablab/kernel/model" + +func newHostsFactory() model.Factory { + return &hostsFactory{} +} + +func (_ *hostsFactory) Build(m *model.Model) error { + for _, host := range m.SelectHosts("*") { + if host.InstanceType == "" { + host.InstanceType = "t2.micro" + } + } + + instanceType, found := m.GetStringVariable("instance_type") + if found { + for _, host := range m.SelectHosts("*") { + host.InstanceType = instanceType + } + } + + instanceResourceType, found := m.GetStringVariable("instance_resource_type") + if found { + for _, host := range m.SelectHosts("*") { + host.InstanceResourceType = instanceResourceType + } + } + + spotPrice, found := m.GetStringVariable("spot_price") + if found { + for _, host := range m.SelectHosts("*") { + host.SpotPrice = spotPrice + } + } + + spotType, found := m.GetStringVariable("spot_type") + if found { + for _, host := range m.SelectHosts("*") { + host.SpotType = spotType + } + } + + return nil +} + +type hostsFactory struct{} diff --git a/zititest/models/smart/main.go b/zititest/models/smart/main.go new file mode 100644 index 000000000..4025e87f9 --- /dev/null +++ b/zititest/models/smart/main.go @@ -0,0 +1,184 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "embed" + + "github.com/openziti/fablab" + "github.com/openziti/fablab/kernel/lib/binding" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fablab/resources" + "github.com/openziti/ziti/zititest/zitilab" +) + +//go:embed config +var configs embed.FS + +func init() { + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) +} + +var smartrouting = &model.Model{ + Id: "smart-routing", + Resources: model.Resources{ + resources.Configs: resources.SubFolder(configs, "config"), + resources.Terraform: resources.DefaultTerraformResources(), + }, + Scope: model.Scope{ + Defaults: model.Variables{ + "zitilib.fabric.data_plane_protocol": "tls", + "credentials.ssh.username": "ubuntu", + "distribution": model.Variables{ + "rsync_bin": "rsync", + "ssh_bin": "ssh", + }, + "ziti_fabric_path": "ziti-fabric", + "instance_type": "t2.micro", + }, + }, + + Factories: []model.Factory{ + newHostsFactory(), + newActionsFactory(), + newStageFactory(), + }, + + Regions: model.Regions{ + "initiator": { + Region: "us-east-1", + Site: "us-east-1a", + Hosts: model.Hosts{ + "ctrl": { + Components: model.Components{ + "ctrl": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + BinaryName: "ziti-controller", + ConfigSrc: "ctrl.yml", + ConfigName: "ctrl.yml", + PublicIdentity: "ctrl", + }, + }, + }, + "001": { + Scope: model.Scope{Tags: model.Tags{"iperf_server"}}, + Components: model.Components{ + "001": { + Scope: model.Scope{Tags: model.Tags{"initiator", "router"}}, + BinaryName: "ziti-router", + ConfigSrc: "ingress_router.yml", + ConfigName: "001.yml", + PublicIdentity: "001", + }, + }, + }, + "loop0": { + Scope: model.Scope{Tags: model.Tags{"loop-dialer"}}, + }, + "loop1": { + Scope: model.Scope{Tags: model.Tags{"loop-dialer"}}, + }, + "loop2": { + Scope: model.Scope{Tags: model.Tags{"loop-dialer"}}, + }, + "loop3": { + Scope: model.Scope{Tags: model.Tags{"loop-dialer"}}, + }, + }, + }, + "transitA": { + Region: "us-east-1", + Site: "us-east-1b", + Hosts: model.Hosts{ + "002": { + Scope: model.Scope{Tags: model.Tags{"router"}}, + Components: model.Components{ + "002": { + BinaryName: "ziti-router", + ConfigSrc: "transit_router.yml", + ConfigName: "002.yml", + PublicIdentity: "002", + }, + }, + }, + }, + }, + "transitB": { + Region: "us-east-1", + Site: "us-east-1c", + Hosts: model.Hosts{ + "004": { + Components: model.Components{ + "004": { + Scope: model.Scope{Tags: model.Tags{"router"}}, + BinaryName: "ziti-router", + ConfigSrc: "transit_router.yml", + ConfigName: "004.yml", + PublicIdentity: "004", + }, + }, + }, + }, + }, + "terminator": { + Region: "us-west-2", + Site: "us-west-2b", + Hosts: model.Hosts{ + "003": { + Components: model.Components{ + "003": { + Scope: model.Scope{Tags: model.Tags{"router", "terminator"}}, + BinaryName: "ziti-router", + ConfigSrc: "egress_router.yml", + ConfigName: "003.yml", + PublicIdentity: "003", + }, + }, + }, + "loop0": { + Scope: model.Scope{Tags: model.Tags{"loop-listener"}}, + }, + "loop1": { + Scope: model.Scope{Tags: model.Tags{"loop-listener"}}, + }, + "loop2": { + Scope: model.Scope{Tags: model.Tags{"loop-listener"}}, + }, + "loop3": { + Scope: model.Scope{Tags: model.Tags{"loop-listener"}}, + }, + }, + }, + }, +} + +func main() { + //smartrouting.VarConfig.EnableDebugLogger() + + model.AddBootstrapExtension( + zitilab.BootstrapWithFallbacks( + &zitilab.BootstrapFromEnv{}, + &zitilab.BootstrapFromFind{}, + )) + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) + + fablab.InitModel(smartrouting) + fablab.Run() +} diff --git a/zititest/models/smart/stages.go b/zititest/models/smart/stages.go new file mode 100644 index 000000000..795aee737 --- /dev/null +++ b/zititest/models/smart/stages.go @@ -0,0 +1,160 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "fmt" + aws_ssh_keys0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + semaphore0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore" + terraform0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform" + "github.com/openziti/fablab/kernel/lib/runlevel/1_configuration/config" + distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution" + "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync" + fablib_5_operation "github.com/openziti/fablab/kernel/lib/runlevel/5_operation" + aws_ssh_keys6 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key" + terraform6 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/models" + zitilab_runlevel_1_configuration "github.com/openziti/ziti/zititest/zitilab/runlevel/1_configuration" + zitilab_5_operation "github.com/openziti/ziti/zititest/zitilab/runlevel/5_operation" + "time" +) + +func newStageFactory() model.Factory { + return &stageFactory{} +} + +// stageFactory is a model.Factory that is responsible for building and connecting the stages that +// represent the various phases of the model. +func (self *stageFactory) Build(m *model.Model) error { + // set up ssh keys (if configured), create the cloud infrastructure and restart all instances after they've been updated + m.Infrastructure = model.InfrastructureStages{ + aws_ssh_keys0.Express(), + terraform0.Express(), + semaphore0.Restart(90 * time.Second), + } + + // pull together the artifacts that will be distributed + // This includes + // 1. keys and certs + // 2. component configurations, which includes controller and router configurations + // 3. loop tester configurations + // 4. The actual binaries, including the controller, router, ziti-fabric CLI and the ziti-fabric-test tool + m.Configuration = model.ConfigurationStages{ + zitilab_runlevel_1_configuration.IfNoPki(zitilab_runlevel_1_configuration.Fabric("smart.test")), + config.Component(), + config.Static([]config.StaticConfig{ + {Src: "10-ambient.loop2.yml", Name: "10-ambient.loop2.yml"}, + {Src: "4k-chatter.loop2.yml", Name: "4k-chatter.loop2.yml"}, + {Src: "remote_identities.yml", Name: "remote_identities.yml"}, + }), + zitilab.DefaultZitiBinaries(), + } + + // Create log directories on hosts that need them + // Push the artifacts gather in the configuration stage up to the hosts + m.Distribution = model.DistributionStages{ + distribution.Locations(models.HasControllerComponent, "logs"), + distribution.Locations(models.HasRouterComponent, "logs"), + distribution.Locations(models.LoopListenerTag, "logs"), + distribution.Locations(models.LoopDialerTag, "logs"), + rsync.Rsync(1), + } + + // Run the bootstrap and start actions + // This will + // 1. reset the controller + // 2. enroll the routers + // 3. create the service and terminator + // 4. Create config files that the ziti-fabric-test loop tool can use to connect and send data + // 5. Ensure the controller and router are started + m.AddActivationActions("bootstrap", "start") + + // In the operating phase, this model launches mesh structure polling, fabric metrics listening, and then creates the correct + // loop2 dialers and listeners that run against the model. When the dialers complete their operation, the joiner will + // join with them, invoking the closer and ending the mesh and metrics pollers. Finally, the instance state is + // persisted as a dump. + if err := self.addOperationStages(m); err != nil { + return err + } + + // finally, dispose of the instances and remove any added keys + m.Disposal = model.DisposalStages{ + terraform6.Dispose(), + aws_ssh_keys6.Dispose(), + } + + return nil +} + +func (self *stageFactory) addOperationStages(m *model.Model) error { + phase := fablib_5_operation.NewPhase() + + m.AddOperatingStage(zitilab_5_operation.Mesh(phase.GetCloser())) + //m.AddOperatingStage(zitilab_5_operation.Metrics(phase.GetCloser())) + + if err := self.addListenerStages(m); err != nil { + return fmt.Errorf("error creating listeners (%w)", err) + } + + m.AddOperatingStage(fablib_5_operation.Timer(5*time.Second, nil)) + + if err := self.dialers(m, phase); err != nil { + return fmt.Errorf("error creating dialers (%w)", err) + } + + m.AddOperatingStage(phase) + m.AddOperatingStage(fablib_5_operation.Persist()) + + return nil +} + +func (_ *stageFactory) addListenerStages(m *model.Model) error { + hosts := m.SelectHosts(models.LoopListenerTag) + if len(hosts) < 1 { + return fmt.Errorf("no '%v' hosts in model", models.LoopListenerTag) + } + + for _, host := range hosts { + m.AddOperatingStage(zitilab_5_operation.LoopListener(host, nil, "tcp:0.0.0.0:8171")) + } + + return nil +} + +func (_ *stageFactory) dialers(m *model.Model, phase fablib_5_operation.Phase) error { + initiator, err := m.SelectHost("component.initiator.router") + if err != nil { + return err + } + + endpoint := fmt.Sprintf("tls:%s:7002", initiator.PublicIp) + + hosts, err := m.MustSelectHosts(models.LoopDialerTag, 1) + if err != nil { + return err + } + + for _, host := range hosts { + m.AddOperatingStage(zitilab_5_operation.LoopDialer(host, "10-ambient.loop2.yml", endpoint, phase.AddJoiner())) + } + + return nil +} + +type stageFactory struct{} diff --git a/zititest/models/stall/FlowControl.json b/zititest/models/stall/FlowControl.json new file mode 100644 index 000000000..c6b68042b --- /dev/null +++ b/zititest/models/stall/FlowControl.json @@ -0,0 +1,1961 @@ +{ + "__inputs": [ + { + "name": "DS_INFLUX", + "label": "influx", + "description": "", + "type": "datasource", + "pluginId": "influxdb", + "pluginName": "InfluxDB" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.4.5" + }, + { + "type": "datasource", + "id": "influxdb", + "name": "InfluxDB", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.windowSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Window Size (Initiator)", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.linkSendBufferSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Link Send Buffer Size (initiator)", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.linkRecvBufferSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Link Send Buffer Reported Recv Size (initiator)", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.recvBuffer.size", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Terminator" + } + ] + } + ], + "title": "Receive Buffer Size (Terminator)", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.successfulAcks", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Successful Acks", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.duplicateAcks", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Duplicate Acks", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retransmits", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retransmits", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retxThreshold", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retx Threshold", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "cps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.dropped_payloads", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Dropped Payloads ", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retxScale", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retx Scale", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "ingress.rx.bytesrate.mean {source: router-ap-0}" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "ingress.rx.bytesrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Ingress Rx", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "egress.tx.bytesrate.mean {source: router-west-0}" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "egress.tx.bytesrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Egress Tx", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "cps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.retransmissions", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Retransmissions", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "cps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUX}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.ack_duplicates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Duplicate Acks", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 35, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-4h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "FlowControl", + "uid": "RVzy7lU7z", + "version": 3, + "weekStart": "" +} \ No newline at end of file diff --git a/zititest/models/stall/action_bootstrap.go b/zititest/models/stall/action_bootstrap.go new file mode 100644 index 000000000..d1e341f0b --- /dev/null +++ b/zititest/models/stall/action_bootstrap.go @@ -0,0 +1,101 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" + "time" +) + +func NewBootstrapAction() model.ActionBinder { + action := &bootstrapAction{} + return action.bind +} + +func (a *bootstrapAction) bind(m *model.Model) model.Action { + workflow := actions.Workflow() + + workflow.AddAction(host.GroupExec("*", 25, "rm -f logs/*")) + workflow.AddAction(component.Stop("#ctrl")) + workflow.AddAction(edge.InitController("#ctrl")) + workflow.AddAction(component.Start("#ctrl")) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + workflow.AddAction(edge.Login("#ctrl")) + + workflow.AddAction(component.StopInParallel(models.EdgeRouterTag, 25)) + workflow.AddAction(edge.InitEdgeRouters(models.EdgeRouterTag, 2)) + workflow.AddAction(edge.InitIdentities(models.SdkAppTag, 2)) + + workflow.AddAction(zitilib_actions.Edge("create", "config", "test-host", "host.v2", ` + { + "terminators" : [ + { + "address" : "localhost", + "port" : 8171, + "protocol" : "tcp", + "portChecks" : [ + { + "address" : "localhost:8172", + "interval" : "1s", + "timeout" : "100ms", + "actions" : [ + { "trigger" : "fail", "action" : "mark unhealthy" }, + { "trigger" : "pass", "action" : "mark healthy" } + ] + } + ] + } + ] + }`)) + + workflow.AddAction(zitilib_actions.Edge("create", "config", "test-intercept", "intercept.v1", ` + { + "addresses": ["test.service"], + "portRanges" : [ + { "low": 8171, "high": 8171 } + ], + "protocols": ["tcp"] + }`)) + + workflow.AddAction(zitilib_actions.Edge("create", "service", "test", "--encryption", "on", "-c", "test-host,test-intercept")) + workflow.AddAction(zitilib_actions.Edge("create", "service", "metrics", "--encryption", "on")) + + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "test-bind", "Bind", "--service-roles", "@test", "--identity-roles", "#terminator")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "test-dial", "Dial", "--service-roles", "@test", "--identity-roles", "#initiator,#client", "--semantic", "AnyOf")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "metrics-dial", "Dial", "--service-roles", "@metrics", "--identity-roles", "#client")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "metrics-bind", "Bind", "--service-roles", "@metrics", "--identity-roles", "#metrics-host")) + + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "metrics-routers", "--edge-router-roles", "@metrics-router", "--identity-roles", "#all")) + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "test-routers", "--edge-router-roles", "@router-ap-0", "--identity-roles", "#client")) + + workflow.AddAction(zitilib_actions.Edge("create", "service-edge-router-policy", "test", "--semantic", "AnyOf", "--service-roles", "@test", "--edge-router-roles", "#initiator,#terminator")) + workflow.AddAction(zitilib_actions.Edge("create", "service-edge-router-policy", "metrics", "--service-roles", "@metrics", "--edge-router-roles", "@metrics-router")) + + workflow.AddAction(component.Stop(models.ControllerTag)) + + return workflow +} + +type bootstrapAction struct{} diff --git a/zititest/models/stall/action_start.go b/zititest/models/stall/action_start.go new file mode 100644 index 000000000..100bc343a --- /dev/null +++ b/zititest/models/stall/action_start.go @@ -0,0 +1,41 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/models" + "time" +) + +func NewStartAction() model.ActionBinder { + action := &startAction{} + return action.bind +} + +func (a *startAction) bind(*model.Model) model.Action { + workflow := actions.Workflow() + workflow.AddAction(component.Start("#ctrl")) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + workflow.AddAction(component.StartInParallel(models.EdgeRouterTag, 25)) + return workflow +} + +type startAction struct{} diff --git a/zititest/models/stall/action_sync_model_edge_state.go b/zititest/models/stall/action_sync_model_edge_state.go new file mode 100644 index 000000000..126faddaa --- /dev/null +++ b/zititest/models/stall/action_sync_model_edge_state.go @@ -0,0 +1,38 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" +) + +func NewSyncModelEdgeStateAction() model.ActionBinder { + action := &syncModelEdgeStateAction{} + return action.bind +} + +func (a *syncModelEdgeStateAction) bind(*model.Model) model.Action { + workflow := actions.Workflow() + workflow.AddAction(edge.Login("#ctrl")) + workflow.AddAction(edge.SyncModelEdgeState(models.EdgeRouterTag)) + return workflow +} + +type syncModelEdgeStateAction struct{} diff --git a/zititest/models/stall/configs/ctrl.yml b/zititest/models/stall/configs/ctrl.yml new file mode 100644 index 000000000..812f96da2 --- /dev/null +++ b/zititest/models/stall/configs/ctrl.yml @@ -0,0 +1,232 @@ +v: 3 + +db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrl.db + +identity: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-client.cert + server_cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-server.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/keys/{{ .Component.PublicIdentity }}.key + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/{{ .Component.PublicIdentity }}-server.chain.pem + +#trace: +# path: ctrl.trace + +profile: +# cpu: +# path: /home/plorenz/tmp/ctrl.cpu.pprof +# memory: +# path: ctrl.memprof + +# the endpoint that routers will connect to the controller over. +ctrl: + listener: tls:0.0.0.0:6262 + options: + # (optional) settings + # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000) + #maxQueuedConnects: 50 + + # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16) + #maxOutstandingConnects: 100 + + # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms) + #connectTimeoutMs: 3000 + + # Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect + #writeTimeout: 15s + + # A listener address which will be sent to connecting routers in order to change their configured controller + # address. If defined, routers will update address configuration to immediately use the new address for future + # connections. The value of newListener must be resolvable both via DNS and validate via certificates + #newListener: tls:localhost:6262 + +# the endpoint that management tools connect to the controller over. +mgmt: + listener: tls:0.0.0.0:10000 + #options: + # (optional) settings + # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000) + #maxQueuedConnects: 50 + # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16) + #maxOutstandingConnects: 100 + # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms) + #connectTimeoutMs: 3000 + + #metrics: + #file: + #path: /tmp/ziti-controller-metrics.log + #maxsizemb: 100:wq + # Supported formats: json, plain + # Defaults to json + #format: plain + #influxdb: + #url: http://localhost:8086 + #database: ziti + +#events: +# jsonLogger: +# subscriptions: +# - type: fabric.routers +# - type: fabric.terminators +# - type: metrics +# sourceFilter: .* +# metricFilter: .*egress.*m1_rate* +# - type: fabric.circuits +# include: +# - created +# - type: edge.sessions +# include: +# - created +# - type: edge.apiSessions +# - type: fabric.usage +# - type: services +# - type: fabric.usage +# - type: edge.entityCounts +# interval: 5s +# handler: +# type: file +# format: json +# path: /tmp/ziti-events.log + +# xctrl_example +# +#example: +# enabled: false +# delay: 5 + +healthChecks: + boltCheck: + # How often to try entering a bolt read tx. Defaults to 30 seconds + interval: 30s + # When to timeout the check. Defaults to 15 seconds + timeout: 15s + # How long to wait before starting the check. Defaults to 15 seconds + initialDelay: 15s + +# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the edge to not run. +edge: + # This section represents the configuration of the Edge API that is served over HTTPS + api: + #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted + # activityUpdateInterval: 90s + #(optional, default 250) The number of API Sessions updated for last activity per transaction + # activityUpdateBatchSize: 250 + # sessionTimeout - optional, default 10m + # The number of minutes before an Edge API session will timeout. Timeouts are reset by + # API requests and connections that are maintained to Edge Routers + sessionTimeout: 30m + # address - required + # The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses + # defined in a bind point's address field for the `edge-client` API in the web section. + address: {{.Host.PublicIp}}:1280 + # enrollment - required + # A section containing settings pertaining to enrollment. + enrollment: + # signingCert - required + # A Ziti Identity configuration section that specifically makes use of the cert and key fields to define + # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert + # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller. + signingCert: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/certs/intermediate.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/intermediate/keys/intermediate.key + + # edgeIdentity - optional + # A section for identity enrollment specific settings + edgeIdentity: + # duration - optional, default 5m + # The length of time that a Ziti Edge Identity enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + # edgeRouter - Optional + # A section for edge router enrollment specific settings. + edgeRouter: + # duration - optional, default 5m + # The length of time that a Ziti Edge Router enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + + +# web - optional +# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many +# bind points. +web: + # name - required + # Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested. + - name: all-apis-localhost + # bindPoints - required + # One or more bind points are required. A bind point specifies an interface (interface:port string) that defines + # where on the host machine the webListener will listen and the address (host:port) that should be used to + # publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for + # incoming address resolution as well as used in responses in the API. + bindPoints: + #interface - required + # A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces + - interface: 0.0.0.0:1280 + + # address - required + # The public address that external incoming requests will be able to resolve. Used in request processing and + # response content that requires full host:port/path addresses. + address: {{.Host.PublicIp}}:1280 + + # newAddress - optional + # A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header + # is present, clients should update location configuration to immediately use the new address for future + # connections. The value of newAddress must be resolvable both via DNS and validate via certificates + #newAddress: localhost:1280 + # identity - optional + # Allows the webListener to have a specific identity instead of defaulting to the root `identity` section. + # identity: + # cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem + # server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem + # key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem + # ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem + # options - optional + # Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are + # used for all http servers started by the current webListener. + options: + # idleTimeout - optional, default 5000ms + # The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high + # can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value + # will cause clients to reconnect on subsequent HTTPs requests. + idleTimeout: 5000ms #http timeouts, new + + # readTimeout - optional, default 5000ms + # The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher + # value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency + # or packet loss. A lower value can risk losing connections to high latency/packet loss clients. + + readTimeout: 5000ms + # writeTimeout - optional, default 10000ms + # The total maximum time in milliseconds that the http server will wait for a single requests to be received and + # responded too. A higher value can allow long running requests to consume resources on the host. A lower value + # can risk ending requests before the server has a chance to respond. + + writeTimeout: 100000ms + # minTLSVersion - optional, default TSL1.2 + # The minimum version of TSL to support + + minTLSVersion: TLS1.2 + # maxTLSVersion - optional, default TSL1.3 + # The maximum version of TSL to support + + maxTLSVersion: TLS1.3 + # apis - required + # Allows one or more APIs to be bound to this webListener + apis: + # binding - required + # Specifies an API to bind to this webListener. Built-in APIs are + # - health-checks + # - edge-management + # - edge-client + # - fabric-management + - binding: health-checks + options: { } + - binding: fabric + - binding: edge-management + # options - variable optional/required + # This section is used to define values that are specified by the API they are associated with. + # These settings are per API. The example below is for the `edge-api` and contains both optional values and + # required values. + options: { } + - binding: edge-client + options: { } diff --git a/zititest/models/stall/configs/router.yml b/zititest/models/stall/configs/router.yml new file mode 100644 index 000000000..6393990c2 --- /dev/null +++ b/zititest/models/stall/configs/router.yml @@ -0,0 +1,70 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.PublicIdentity}} +{{$ctrl_ip := publicIp "component#ctrl"}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +enableDebugOps: true + +identity: + cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/pki/intermediate/keys/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/pki/intermediate/certs/{{$identity}}-server.chain.pem + +ctrl: + endpoint: tls:{{$ctrl_ip}}:6262 + +healthChecks: + ctrlPingCheck: + # How often to ping the controller over the control channel. Defaults to 30 seconds + interval: 30s + # When to timeout the ping. Defaults to 15 seconds + timeout: 15s + # How long to wait before pinging the controller. Defaults to 15 seconds + initialDelay: 15s + +metrics: + reportInterval: 15s + messageQueueSize: 10 + +link: + listeners: + - binding: transport + bind: tls:0.0.0.0:6000 + advertise: tls:{{$router_ip}}:6000 + dialers: + - binding: transport + +listeners: +{{if .Component.HasTag "tunneler"}} + - binding: tunnel + options: + mode: tproxy +{{end}} + - binding: edge + address: tls:0.0.0.0:6262 + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: {{ .Host.PublicIp }}:6262 + +# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + ip: + - {{ .Host.PublicIp }} + diff --git a/zititest/models/stall/configs/test.loop3.yml b/zititest/models/stall/configs/test.loop3.yml new file mode 100644 index 000000000..61ad379e8 --- /dev/null +++ b/zititest/models/stall/configs/test.loop3.yml @@ -0,0 +1,45 @@ +workloads: + - name: chatter + # 100 * 20 = 2000 msgs/sec + # 2000 * 1k = 2MB/s + # 2MB/s * 3 hosts = 6 MB/s each directino + + # 100 * 2 = 200 msgs/sec + # 200 * 10k = 2MB/s + # 2MB/s * 3 hosts = 6 MB/s each directino + + concurrency: 5 + + # 5 client + # 50 msgs/sec * 10k = 0.5MB/s + # 0.5MB/s * 5 clients = 2.5 MB/s + # 52 * 2.5 = 130 MB/s + # 128 MB/s = 1 Gb/s + + dialer: + txRequests: 10000000 + txPacing: 0 + txMaxJitter: 0 + txPauseEvery: 0m + txPauseFor: 30s + rxTimeout: 240000 + payloadMinBytes: 60000 + payloadMaxBytes: 60000 + latencyFrequency: 20 + + listener: + txRequests: 0 + txPacing: 0 + txMaxJitter: 0 + rxPacing: 0ms + rxPauseEvery: 0s + rxPauseFor: 10s + rxTimeout: 240000 + payloadMinBytes: 10240 + payloadMaxBytes: 10240 + latencyFrequency: 20 + +metrics: + service: metrics + interval: 15s + clientId: {{.Component.PublicIdentity}} diff --git a/zititest/models/stall/main.go b/zititest/models/stall/main.go new file mode 100644 index 000000000..28e94f39e --- /dev/null +++ b/zititest/models/stall/main.go @@ -0,0 +1,211 @@ +package main + +import ( + "embed" + _ "embed" + "github.com/openziti/fablab" + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/binding" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform" + "github.com/openziti/fablab/kernel/lib/runlevel/1_configuration/config" + distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution" + "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync" + aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fablab/resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + zitilib_runlevel_1_configuration "github.com/openziti/ziti/zititest/zitilab/runlevel/1_configuration" + "os" + "time" +) + +//go:embed configs +var configResource embed.FS + +type scaleStrategy struct{} + +func (self scaleStrategy) IsScaled(entity model.Entity) bool { + return entity.GetType() == model.EntityTypeHost && entity.GetScope().HasTag("scaled") +} + +func (self scaleStrategy) GetEntityCount(entity model.Entity) uint32 { + if entity.GetType() == model.EntityTypeHost && entity.GetScope().HasTag("scaled") { + return 4 + } + return 1 +} + +var m = &model.Model{ + Id: "stall", + Scope: model.Scope{ + Defaults: model.Variables{ + "environment": "ziti-stall-test", + "credentials": model.Variables{ + "ssh": model.Variables{ + "username": "ubuntu", + }, + "edge": model.Variables{ + "username": "admin", + "password": "admin", + }, + }, + "metrics": model.Variables{ + "influxdb": model.Variables{ + "url": "http://localhost:8086", + "db": "ziti", + }, + }, + }, + }, + StructureFactories: []model.Factory{ + model.NewScaleFactoryWithDefaultEntityFactory(scaleStrategy{}), + }, + Factories: []model.Factory{ + newStageFactory(), + }, + Resources: model.Resources{ + resources.Configs: resources.SubFolder(configResource, "configs"), + resources.Binaries: os.DirFS("/home/plorenz/go/bin"), + resources.Terraform: resources.DefaultTerraformResources(), + }, + Regions: model.Regions{ + "us-east-1": { + Region: "us-east-1", + Site: "us-east-1a", + Hosts: model.Hosts{ + "ctrl": { + InstanceType: "c5.large", + Components: model.Components{ + "ctrl": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + BinaryName: "ziti-controller", + ConfigSrc: "ctrl.yml", + ConfigName: "ctrl.yml", + PublicIdentity: "ctrl", + }, + }, + }, + "metrics-router": { + InstanceType: "c5.large", + Components: model.Components{ + "metrics-router": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "no-traversal"}}, + BinaryName: "ziti-router", + ConfigSrc: "router.yml", + ConfigName: "metrics-router.yml", + PublicIdentity: "metrics-router", + }, + }, + }, + }, + }, + "us-west-2": { + Region: "us-west-2", + Site: "us-west-2b", + Hosts: model.Hosts{ + "router-west-{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + InstanceType: "c5.large", + Components: model.Components{ + "router-west-{{ .Host.ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "tunneler", "terminator"}}, + BinaryName: "ziti-router", + ConfigSrc: "router.yml", + ConfigName: "router-west-{{ .Host.ScaleIndex }}.yml", + PublicIdentity: "router-west-{{ .Host.ScaleIndex }}", + RunWithSudo: true, + }, + "loop-listener-{{ .Host.ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"sdk-app", "service"}}, + BinaryName: "ziti-fabric-test", + PublicIdentity: "loop-listener-{{ .Host.ScaleIndex }}", + }, + }, + }, + }, + }, + "ap-southeast-1": { + Region: "ap-southeast-1", + Site: "ap-southeast-1a", + Hosts: model.Hosts{ + "router-ap-{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + InstanceType: "c5.large", + Components: model.Components{ + "router-ap-{{ .Host.ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "tunneler", "initiator"}}, + BinaryName: "ziti-router", + ConfigSrc: "router.yml", + ConfigName: "router-ap-{{ .Host.ScaleIndex }}.yml", + PublicIdentity: "router-ap-{{ .Host.ScaleIndex }}", + RunWithSudo: true, + }, + "loop-client-{{ .Host.ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"sdk-app", "client"}}, + BinaryName: "ziti-fabric-test", + ConfigSrc: "test.loop3.yml", + ConfigName: "test.loop3.yml", + PublicIdentity: "loop-client-{{ .Host.ScaleIndex }}", + }, + }, + }, + }, + }, + }, + + Actions: model.ActionBinders{ + "bootstrap": NewBootstrapAction(), + "start": NewStartAction(), + "stop": model.Bind(component.StopInParallel("*", 15)), + "stopSdkApps": model.Bind(component.StopInParallel(".sdk-app", 15)), + "syncModelEdgeState": NewSyncModelEdgeStateAction(), + "clean": model.Bind(actions.Workflow( + component.StopInParallel("*", 15), + host.GroupExec("*", 25, "rm -f logs/*"), + )), + "login": model.Bind(edge.Login("#ctrl")), + }, + + Infrastructure: model.InfrastructureStages{ + aws_ssh_key.Express(), + terraform_0.Express(), + semaphore_0.Restart(90 * time.Second), + }, + + Configuration: model.ConfigurationStages{ + zitilib_runlevel_1_configuration.IfPkiNeedsRefresh( + zitilib_runlevel_1_configuration.Fabric("stall.test"), + ), + config.Component(), + zitilab.DefaultZitiBinaries(), + }, + + Distribution: model.DistributionStages{ + distribution.DistributeSshKey("*"), + distribution.Locations("*", "logs"), + rsync.RsyncStaged(), + }, + + Disposal: model.DisposalStages{ + terraform.Dispose(), + aws_ssh_key2.Dispose(), + }, +} + +func main() { + m.AddActivationActions("stop", "bootstrap", "start", "syncModelEdgeState") + // m.VarConfig.EnableDebugLogger() + + model.AddBootstrapExtension(&zitilab.BootstrapFromEnv{}) + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) + + fablab.InitModel(m) + fablab.Run() +} diff --git a/zititest/models/stall/stages.go b/zititest/models/stall/stages.go new file mode 100644 index 000000000..9b3ca2db6 --- /dev/null +++ b/zititest/models/stall/stages.go @@ -0,0 +1,101 @@ +package main + +import ( + "fmt" + fablib_5_operation "github.com/openziti/fablab/kernel/lib/runlevel/5_operation" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/models" + zitilib_5_operation "github.com/openziti/ziti/zititest/zitilab/runlevel/5_operation" + "strings" + "time" +) + +func newStageFactory() model.Factory { + return &stageFactory{} +} + +func (self *stageFactory) Build(m *model.Model) error { + // m.MetricsHandlers = append(m.MetricsHandlers, model.StdOutMetricsWriter{}) + + runPhase := fablib_5_operation.NewPhase() + //cleanupPhase := fablib_5_operation.NewPhase() + + clientMetrics := zitilib_5_operation.NewClientMetricsWithIdMapper("metrics", runPhase.GetCloser(), func(s string) string { + return "component#" + s + }) + + m.AddActivationStage(clientMetrics) + + m.AddOperatingActions("stopSdkApps", "syncModelEdgeState") + m.AddOperatingStage(fablib_5_operation.InfluxMetricsReporter()) + //m.AddOperatingStage(zitilib_5_operation.Mesh(runPhase.GetCloser())) + m.AddOperatingStage(zitilib_5_operation.ModelMetricsWithIdMapper(runPhase.GetCloser(), func(id string) string { + if id == "ctrl" { + return "#ctrl" + } + id = strings.ReplaceAll(id, ".", ":") + return "component.edgeId:" + id + })) + + m.AddOperatingStage(zitilib_5_operation.CircuitMetrics(5*time.Second, runPhase.GetCloser(), func(id string) string { + id = strings.ReplaceAll(id, ".", ":") + return "component.edgeId:" + id + })) + + m.AddOperatingStage(clientMetrics) + + //for _, host := range m.SelectHosts("*") { + // m.AddOperatingStage(fablib_5_operation.StreamSarMetrics(host, 5, 3, runPhase, cleanupPhase)) + //} + + if err := self.listeners(m); err != nil { + return fmt.Errorf("error creating listeners (%w)", err) + } + + m.AddOperatingStage(fablib_5_operation.Timer(5*time.Second, nil)) + + if err := self.dialers(m, runPhase); err != nil { + return fmt.Errorf("error creating dialers (%w)", err) + } + + m.AddOperatingStage(runPhase) + m.AddOperatingStage(fablib_5_operation.Persist()) + + return nil +} + +func (_ *stageFactory) listeners(m *model.Model) error { + components := m.SelectComponents(models.ServiceTag) + if len(components) < 1 { + return fmt.Errorf("no '%v' components in model", "#loop.listener") + } + + // only start 1 listener + c := components[0] + + remoteConfigFile := fmt.Sprintf("/home/%v/fablab/cfg/%v.json", m.MustVariable("credentials.ssh.username"), c.PublicIdentity) + stage := zitilib_5_operation.Loop3Listener(c.GetHost(), nil, "tcp:0.0.0.0:8171", + "--config-file", remoteConfigFile, "--health-check-addr 127.0.0.1:8172") + m.AddOperatingStage(stage) + + return nil +} + +func (_ *stageFactory) dialers(m *model.Model, phase fablib_5_operation.Phase) error { + var components []*model.Component + components = m.SelectComponents(models.ClientTag) + if len(components) < 1 { + return fmt.Errorf("no '%v' components in model", models.ClientTag) + } + + // only start 1 dialer + c := components[0] + + remoteConfigFile := fmt.Sprintf("/home/%v/fablab/cfg/%v.json", m.MustVariable("credentials.ssh.username"), c.PublicIdentity) + stage := zitilib_5_operation.Loop3Dialer(c.GetHost(), c.ConfigName, "tcp:test.service:8171", phase.AddJoiner(), "--config-file", remoteConfigFile, "-d") + m.AddOperatingStage(stage) + + return nil +} + +type stageFactory struct{} diff --git a/network-tests/test_resources/resource.go b/zititest/models/test_resources/resource.go similarity index 100% rename from network-tests/test_resources/resource.go rename to zititest/models/test_resources/resource.go diff --git a/network-tests/test_resources/terraform/main.tf b/zititest/models/test_resources/terraform/main.tf similarity index 100% rename from network-tests/test_resources/terraform/main.tf rename to zititest/models/test_resources/terraform/main.tf diff --git a/network-tests/test_resources/terraform/ondemand_instance/main.tf b/zititest/models/test_resources/terraform/ondemand_instance/main.tf similarity index 100% rename from network-tests/test_resources/terraform/ondemand_instance/main.tf rename to zititest/models/test_resources/terraform/ondemand_instance/main.tf diff --git a/network-tests/test_resources/terraform/vpc/main.tf b/zititest/models/test_resources/terraform/vpc/main.tf similarity index 100% rename from network-tests/test_resources/terraform/vpc/main.tf rename to zititest/models/test_resources/terraform/vpc/main.tf diff --git a/network-tests/tests/files_test.go b/zititest/tests/files_test.go similarity index 72% rename from network-tests/tests/files_test.go rename to zititest/tests/files_test.go index 8d3559533..1b6ca2b90 100644 --- a/network-tests/tests/files_test.go +++ b/zititest/tests/files_test.go @@ -31,6 +31,12 @@ var hashes = map[string]string{ "20MB": "8f4e33f3dc3e414ff94e5fb6905cba8c", } +var timeouts = map[string]time.Duration{ + "1KB": 5 * time.Second, + "100KB": 5 * time.Second, + "20MB": 40 * time.Second, +} + type httpClient string const ( @@ -39,20 +45,30 @@ const ( ) func TestCurlFiles(t *testing.T) { - for _, clientType := range []string{"ert"} { // add zet back - for _, hostType := range []string{"ert"} { // add zet back - for _, client := range []httpClient{ClientCurl, ClientWget} { - for _, encrypted := range []bool{true, false} { - for _, size := range []string{"1KB", "100KB", "20MB"} { - testFileDownload(t, clientType, client, hostType, encrypted, size, 20*time.Second) + for _, hostType := range []string{"ert", "zet", "ziti-tunnel"} { + for _, clientType := range []string{"ert", "zet", "ziti-tunnel"} { + for _, encrypted := range []bool{true, false} { + testFileDownload(t, clientType, ClientCurl, hostType, encrypted, "1KB") + } + } + } + + for _, size := range []string{"100KB", "20MB"} { + for _, clientType := range []string{"ert", "zet"} { + for _, hostType := range []string{"ert", "zet"} { + for _, client := range []httpClient{ClientCurl, ClientWget} { + for _, encrypted := range []bool{true, false} { + testFileDownload(t, clientType, client, hostType, encrypted, size) } } } } } + + testFileDownload(t, "ziti-tunnel", ClientCurl, "ziti-tunnel", true, "20MB") } -func testFileDownload(t *testing.T, hostSelector string, client httpClient, hostType string, encrypted bool, fileSize string, timeout time.Duration) { +func testFileDownload(t *testing.T, hostSelector string, client httpClient, hostType string, encrypted bool, fileSize string) { encDesk := "encrypted" if !encrypted { encDesk = "unencrypted" @@ -78,6 +94,7 @@ func testFileDownload(t *testing.T, hostSelector string, client httpClient, host cmd = fmt.Sprintf(`set -o pipefail; wget --no-check-certificate --header "Host: ziti-smoketest-files.s3-us-west-1.amazonaws.com" -O - -t 5 -T 5 %s | md5sum`, url) } + timeout := timeouts[fileSize] o, err := lib.RemoteExecAllWithTimeout(sshConfigFactory, timeout, cmd) req.NoError(err) req.Equal(hashes[fileSize], o[0:32]) diff --git a/network-tests/tests/matrix.md b/zititest/tests/matrix.md similarity index 100% rename from network-tests/tests/matrix.md rename to zititest/tests/matrix.md diff --git a/network-tests/tests/model_test.go b/zititest/tests/model_test.go similarity index 96% rename from network-tests/tests/model_test.go rename to zititest/tests/model_test.go index ee3589479..1b990b707 100644 --- a/network-tests/tests/model_test.go +++ b/zititest/tests/model_test.go @@ -19,7 +19,7 @@ package tests import ( "github.com/openziti/fablab" "github.com/openziti/fablab/kernel/model" - "github.com/openziti/ziti/network-tests/simple" + "github.com/openziti/ziti/zititest/models/simple" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/network-tests/utils/actions/echoServer.go b/zititest/utils/actions/echoServer.go similarity index 100% rename from network-tests/utils/actions/echoServer.go rename to zititest/utils/actions/echoServer.go diff --git a/network-tests/utils/ziti-echo/cmd/client.go b/zititest/utils/ziti-echo/cmd/client.go similarity index 84% rename from network-tests/utils/ziti-echo/cmd/client.go rename to zititest/utils/ziti-echo/cmd/client.go index 36928b60b..91d72ee36 100644 --- a/network-tests/utils/ziti-echo/cmd/client.go +++ b/zititest/utils/ziti-echo/cmd/client.go @@ -3,7 +3,6 @@ package cmd import ( "context" "fmt" - "github.com/openziti/sdk-golang/ziti/config" "io" "log" "net" @@ -28,19 +27,11 @@ func init() { } func echoClient(cmd *cobra.Command, args []string) { - cfg, err := config.NewFromFile(identityFile) + zitiContext, err := ziti.NewContextFromFile(identityFile) if err != nil { log.Fatal(err) } - zitiContext := ziti.NewContextWithConfig(cfg) - /* - zitiContext, err := ziti.NewContextFromFile(identityFile) - if err != nil { - log.Fatal(err) - } - */ - dial := func(_ context.Context, _, addr string) (net.Conn, error) { service := strings.Split(addr, ":")[0] return zitiContext.Dial(service) diff --git a/network-tests/utils/ziti-echo/cmd/root.go b/zititest/utils/ziti-echo/cmd/root.go similarity index 100% rename from network-tests/utils/ziti-echo/cmd/root.go rename to zititest/utils/ziti-echo/cmd/root.go diff --git a/network-tests/utils/ziti-echo/cmd/server.go b/zititest/utils/ziti-echo/cmd/server.go similarity index 86% rename from network-tests/utils/ziti-echo/cmd/server.go rename to zititest/utils/ziti-echo/cmd/server.go index 05f9c1c88..ee7a45fee 100644 --- a/network-tests/utils/ziti-echo/cmd/server.go +++ b/zititest/utils/ziti-echo/cmd/server.go @@ -1,7 +1,6 @@ package cmd import ( - "github.com/openziti/sdk-golang/ziti/config" "log" "net" "net/http" @@ -64,18 +63,10 @@ func (s *zitiEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) { } func (s *zitiEchoServer) run() (err error) { - config, err := config.NewFromFile(s.identityJson) + zitiContext, err := ziti.NewContextFromFile(s.identityJson) if err != nil { return err } - - zitiContext := ziti.NewContextWithConfig(config) - /* - zitiContext, err := ziti.NewContextFromFile(s.identityJson) - if err != nil { - return err - } - */ if s.listener, err = zitiContext.Listen("echo"); err != nil { return err } diff --git a/zititest/utils/ziti-echo/main.go b/zititest/utils/ziti-echo/main.go new file mode 100644 index 000000000..f81ee18e2 --- /dev/null +++ b/zititest/utils/ziti-echo/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/openziti/ziti/zititest/utils/ziti-echo/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/zititest/zitilab/actions/consul.go b/zititest/zitilab/actions/consul.go new file mode 100644 index 000000000..406e1539e --- /dev/null +++ b/zititest/zitilab/actions/consul.go @@ -0,0 +1,41 @@ +package zitilib_actions + +import ( + "fmt" + + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" +) + +type consulStart struct { + hostSpec string + consulServer string + configDir string + dataPath string + logFile string +} + +func StartConsul(hostSpec, consulServer, configDir, dataPath, logFile string) model.Action { + return &consulStart{ + hostSpec: hostSpec, + consulServer: consulServer, + configDir: configDir, + dataPath: dataPath, + logFile: logFile, + } +} + +func (cs *consulStart) Execute(m *model.Model) error { + return m.ForEachHost(cs.hostSpec, 24, func(c *model.Host) error { + ssh := lib.NewSshConfigFactory(c) + + cmd := fmt.Sprintf("screen -d -m nohup consul agent -join %s -config-dir %s -data-dir %s -log-file %s 2>&1 &", cs.consulServer, cs.configDir, cs.dataPath, cs.logFile) + + if output, err := lib.RemoteExec(ssh, cmd); err != nil { + logrus.Errorf("error starting consul service [%s] (%v)", output, err) + return err + } + return nil + }) +} diff --git a/zititest/zitilab/actions/edge/ctrl_init.go b/zititest/zitilab/actions/edge/ctrl_init.go new file mode 100644 index 000000000..79dda3f5c --- /dev/null +++ b/zititest/zitilab/actions/edge/ctrl_init.go @@ -0,0 +1,77 @@ +package edge + +import ( + "errors" + "fmt" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" +) + +func InitController(componentSpec string) model.Action { + return &edgeInit{ + componentSpec: componentSpec, + } +} + +func (init *edgeInit) Execute(m *model.Model) error { + username := m.MustStringVariable("credentials.edge.username") + password := m.MustStringVariable("credentials.edge.password") + + if username == "" { + return errors.New("variable credentials/edge/username must be a string") + } + + if password == "" { + return errors.New("variable credentials/edge/password must be a string") + } + + for _, c := range m.SelectComponents(init.componentSpec) { + sshConfigFactory := lib.NewSshConfigFactory(c.GetHost()) + + tmpl := "rm -f /home/%v/fablab/ctrl.db && set -o pipefail; /home/%s/fablab/bin/%s --log-formatter pfxlog edge init /home/%s/fablab/cfg/%s -u %s -p %s 2>&1 | tee logs/%s.edge.init.log" + if err := host.Exec(c.GetHost(), fmt.Sprintf(tmpl, sshConfigFactory.User(), sshConfigFactory.User(), c.BinaryName, sshConfigFactory.User(), c.ConfigName, username, password, c.BinaryName)).Execute(m); err != nil { + return err + } + } + + return nil +} + +type edgeInit struct { + componentSpec string +} + +func InitRaftController(componentSpec string) model.Action { + return &raftInit{ + componentSpec: componentSpec, + } +} + +func (init *raftInit) Execute(m *model.Model) error { + username := m.MustStringVariable("credentials.edge.username") + password := m.MustStringVariable("credentials.edge.password") + + if username == "" { + return errors.New("variable credentials/edge/username must be a string") + } + + if password == "" { + return errors.New("variable credentials/edge/password must be a string") + } + + for _, c := range m.SelectComponents(init.componentSpec) { + sshConfigFactory := lib.NewSshConfigFactory(c.GetHost()) + + tmpl := "set -o pipefail; /home/%s/fablab/bin/ziti agent controller init %s %s default.admin 2>&1 | tee logs/controller.edge.init.log" + if err := host.Exec(c.GetHost(), fmt.Sprintf(tmpl, sshConfigFactory.User(), username, password)).Execute(m); err != nil { + return err + } + } + + return nil +} + +type raftInit struct { + componentSpec string +} diff --git a/zititest/zitilab/actions/edge/get_entity_id.go b/zititest/zitilab/actions/edge/get_entity_id.go new file mode 100644 index 000000000..e8589292e --- /dev/null +++ b/zititest/zitilab/actions/edge/get_entity_id.go @@ -0,0 +1,38 @@ +package edge + +import ( + "fmt" + "github.com/Jeffail/gabs" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/cli" + "github.com/pkg/errors" +) + +func GetEntityId(m *model.Model, entityType string, name string) (string, error) { + output, err := cli.Exec(m, "edge", "list", entityType, "--output-json", + fmt.Sprintf(`name="%v" limit none`, name)) + if err != nil { + return "", err + } + + l, err := gabs.ParseJSON([]byte(output)) + if err != nil { + return "", err + } + + data := l.Path("data") + if data == nil { + return "", nil + } + + entities, err := data.Children() + if err != nil { + return "", err + } + + for _, entity := range entities { + return entity.S("id").Data().(string), nil + } + + return "", errors.Errorf("no entity of type %v found with name %v", entityType, name) +} diff --git a/zititest/zitilab/actions/edge/init_identities.go b/zititest/zitilab/actions/edge/init_identities.go new file mode 100644 index 000000000..c05bf5275 --- /dev/null +++ b/zititest/zitilab/actions/edge/init_identities.go @@ -0,0 +1,57 @@ +package edge + +import ( + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/cli" + "path/filepath" + "strings" +) + +func InitIdentities(componentSpec string, concurrency int) model.Action { + return &initIdentitiesAction{ + componentSpec: componentSpec, + concurrency: concurrency, + } +} + +func (action *initIdentitiesAction) Execute(m *model.Model) error { + return m.ForEachComponent(action.componentSpec, action.concurrency, func(c *model.Component) error { + if err := zitilib_actions.EdgeExec(m, "delete", "identity", c.PublicIdentity); err != nil { + return err + } + + return action.createAndEnrollIdentity(c) + }) +} + +func (action *initIdentitiesAction) createAndEnrollIdentity(c *model.Component) error { + ssh := lib.NewSshConfigFactory(c.GetHost()) + + jwtFileName := filepath.Join(model.ConfigBuild(), c.PublicIdentity+".jwt") + + err := zitilib_actions.EdgeExec(c.GetModel(), "create", "identity", "service", c.PublicIdentity, + "--jwt-output-file", jwtFileName, + "-a", strings.Join(c.Tags, ",")) + + if err != nil { + return err + } + + configFileName := filepath.Join(model.ConfigBuild(), c.PublicIdentity+".json") + + _, err = cli.Exec(c.GetModel(), "edge", "enroll", "--jwt", jwtFileName, "--out", configFileName) + + if err != nil { + return err + } + + remoteConfigFile := "/home/ubuntu/fablab/cfg/" + c.PublicIdentity + ".json" + return lib.SendFile(ssh, configFileName, remoteConfigFile) +} + +type initIdentitiesAction struct { + componentSpec string + concurrency int +} diff --git a/zititest/zitilab/actions/edge/init_routers.go b/zititest/zitilab/actions/edge/init_routers.go new file mode 100644 index 000000000..38385f37b --- /dev/null +++ b/zititest/zitilab/actions/edge/init_routers.go @@ -0,0 +1,85 @@ +package edge + +import ( + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "path/filepath" + "strings" +) + +func InitEdgeRouters(componentSpec string, concurrency int) model.Action { + return &initEdgeRoutersAction{ + componentSpec: componentSpec, + concurrency: concurrency, + } +} + +func (action *initEdgeRoutersAction) Execute(m *model.Model) error { + return m.ForEachComponent(action.componentSpec, action.concurrency, func(c *model.Component) error { + if err := zitilib_actions.EdgeExec(m, "delete", "edge-router", c.PublicIdentity); err != nil { + pfxlog.Logger(). + WithError(err). + WithField("router", c.PublicIdentity). + Warn("unable to delete router (may not be present") + } + + return action.createAndEnrollRouter(c) + }) +} + +func (action *initEdgeRoutersAction) createAndEnrollRouter(c *model.Component) error { + ssh := lib.NewSshConfigFactory(c.GetHost()) + + jwtFileName := filepath.Join(model.ConfigBuild(), c.PublicIdentity+".jwt") + + attributes := strings.Join(c.Tags, ",") + + args := []string{"create", "edge-router", c.PublicIdentity, "-j", "--jwt-output-file", jwtFileName, "-a", attributes} + + isTunneler := c.HasLocalOrAncestralTag("tunneler") + if isTunneler { + args = append(args, "--tunneler-enabled") + } + + if c.HasLocalOrAncestralTag("no-traversal") { + args = append(args, "--no-traversal") + } + + if err := zitilib_actions.EdgeExec(c.GetModel(), args...); err != nil { + return err + } + + if isTunneler { + if err := zitilib_actions.EdgeExec(c.GetModel(), "update", "identity", c.PublicIdentity, "-a", attributes); err != nil { + return err + } + } + + remoteJwt := "/home/ubuntu/fablab/cfg/" + c.PublicIdentity + ".jwt" + if err := lib.SendFile(ssh, jwtFileName, remoteJwt); err != nil { + return err + } + + tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%s enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log " + cmds := []string{ + "mkdir -p /home/ubuntu/logs", + fmt.Sprintf(tmpl, c.BinaryName, c.ConfigName, remoteJwt, c.ConfigName), + } + + if isTunneler { + cmds = append(cmds, + "sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf", + "sudo systemctl restart systemd-resolved") + } + + return host.Exec(c.GetHost(), cmds...).Execute(c.GetModel()) +} + +type initEdgeRoutersAction struct { + componentSpec string + concurrency int +} diff --git a/zititest/zitilab/actions/edge/login.go b/zititest/zitilab/actions/edge/login.go new file mode 100644 index 000000000..359ac1c8c --- /dev/null +++ b/zititest/zitilab/actions/edge/login.go @@ -0,0 +1,51 @@ +package edge + +import ( + "errors" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/ziti/cmd/common" + "github.com/openziti/ziti/zititest/zitilab/cli" + "path/filepath" +) + +func Login(componentSelector string) model.Action { + return &login{ + componentSelector: componentSelector, + } +} + +func (l *login) Execute(m *model.Model) error { + ctrl, err := m.SelectComponent(l.componentSelector) + if err != nil { + return err + } + + username := m.MustStringVariable("credentials.edge.username") + password := m.MustStringVariable("credentials.edge.password") + edgeApiBaseUrl := ctrl.Host.PublicIp + ":1280" + + caChain := filepath.Join(model.PkiBuild(), ctrl.PublicIdentity, "certs", ctrl.PublicIdentity+".cert") + + if username == "" { + return errors.New("variable credentials/edge/username must be a string") + } + + if password == "" { + return errors.New("variable credentials/edge/password must be a string") + } + + if _, err = cli.Exec(m, "edge", "login", edgeApiBaseUrl, "-i", model.ActiveInstanceId(), "--ca", caChain, "-u", username, "-p", password); err != nil { + return err + } + + if _, err = cli.Exec(m, "edge", "use", model.ActiveInstanceId()); err != nil { + return err + } + + common.CliIdentity = model.ActiveInstanceId() + return nil +} + +type login struct { + componentSelector string +} diff --git a/zititest/zitilab/actions/edge/raft_join.go b/zititest/zitilab/actions/edge/raft_join.go new file mode 100644 index 000000000..c975557ee --- /dev/null +++ b/zititest/zitilab/actions/edge/raft_join.go @@ -0,0 +1,36 @@ +package edge + +import ( + "fmt" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" + "github.com/pkg/errors" +) + +func RaftJoin(componentSpec string) model.Action { + return &raftJoin{ + componentSpec: componentSpec, + } +} + +type raftJoin struct { + componentSpec string +} + +func (self *raftJoin) Execute(m *model.Model) error { + ctrls := m.SelectComponents(self.componentSpec) + if len(ctrls) < 1 { + return errors.Errorf("no controllers found with spec '%v'", self.componentSpec) + } + primary := ctrls[0] + sshConfigFactory := lib.NewSshConfigFactory(primary.GetHost()) + for _, c := range ctrls[1:] { + tmpl := "/home/%s/fablab/bin/ziti agent cluster add %v --id %v" + if err := host.Exec(primary.GetHost(), fmt.Sprintf(tmpl, sshConfigFactory.User(), "tls:"+c.Host.PublicIp+":6262", c.PublicIdentity)).Execute(m); err != nil { + return err + } + } + + return nil +} diff --git a/zititest/zitilab/actions/edge/reenroll_routers.go b/zititest/zitilab/actions/edge/reenroll_routers.go new file mode 100644 index 000000000..78a3fe336 --- /dev/null +++ b/zititest/zitilab/actions/edge/reenroll_routers.go @@ -0,0 +1,59 @@ +package edge + +import ( + "fmt" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "path/filepath" +) + +func ReEnrollEdgeRouters(componentSpec string, concurrency int) model.Action { + return &reEnrollEdgeRoutersAction{ + componentSpec: componentSpec, + concurrency: concurrency, + } +} + +func (action *reEnrollEdgeRoutersAction) Execute(m *model.Model) error { + return m.ForEachComponent(action.componentSpec, action.concurrency, func(c *model.Component) error { + return action.reEnrollRouter(c) + }) +} + +func (action *reEnrollEdgeRoutersAction) reEnrollRouter(c *model.Component) error { + ssh := lib.NewSshConfigFactory(c.GetHost()) + + jwtFileName := filepath.Join(model.ConfigBuild(), c.PublicIdentity+".jwt") + + args := []string{"re-enroll", "edge-router", c.PublicIdentity, "-j", "--jwt-output-file", jwtFileName} + + if err := zitilib_actions.EdgeExec(c.GetModel(), args...); err != nil { + return err + } + + remoteJwt := "/home/ubuntu/fablab/cfg/" + c.PublicIdentity + ".jwt" + if err := lib.SendFile(ssh, jwtFileName, remoteJwt); err != nil { + return err + } + + tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%s enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log " + cmds := []string{ + "mkdir -p /home/ubuntu/logs", + fmt.Sprintf(tmpl, c.BinaryName, c.ConfigName, remoteJwt, c.ConfigName), + } + + if c.HasLocalOrAncestralTag("tunneler") { + cmds = append(cmds, + "sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf", + "sudo systemctl restart systemd-resolved") + } + + return host.Exec(c.GetHost(), cmds...).Execute(c.GetModel()) +} + +type reEnrollEdgeRoutersAction struct { + componentSpec string + concurrency int +} diff --git a/zititest/zitilab/actions/edge/sync_model_edge_state.go b/zititest/zitilab/actions/edge/sync_model_edge_state.go new file mode 100644 index 000000000..1b85bb815 --- /dev/null +++ b/zititest/zitilab/actions/edge/sync_model_edge_state.go @@ -0,0 +1,60 @@ +package edge + +import ( + "github.com/Jeffail/gabs" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/pkg/errors" + "strings" +) + +func SyncModelEdgeState(componentSpec string) model.Action { + return &syncModelEdgeStateAction{ + componentSpec: componentSpec, + } +} + +func (action *syncModelEdgeStateAction) Execute(m *model.Model) error { + routerComponents := m.SelectComponents(action.componentSpec) + if len(routerComponents) == 0 { + return errors.Errorf("no router components found for selector '%v'", action.componentSpec) + } + + output, err := zitilib_actions.EdgeExecWithOutput(m, "list", "edge-routers", "--output-json", "true limit none") + if err != nil { + return err + } + + l, err := gabs.ParseJSON([]byte(output)) + if err != nil { + return err + } + + data := l.Path("data") + if data == nil { + return nil + } + + routers, err := data.Children() + if err != nil { + return err + } + + for _, router := range routers { + routerId := router.S("id").Data().(string) + routerName := router.S("name").Data().(string) + + for _, c := range routerComponents { + if c.PublicIdentity == routerName { + routerId = strings.ReplaceAll(routerId, ".", ":") + c.Tags = append(c.Tags, "edgeId:"+routerId) + } + } + } + + return nil +} + +type syncModelEdgeStateAction struct { + componentSpec string +} diff --git a/zititest/zitilab/actions/edge_cli.go b/zititest/zitilab/actions/edge_cli.go new file mode 100644 index 000000000..d67c04ab4 --- /dev/null +++ b/zititest/zitilab/actions/edge_cli.go @@ -0,0 +1,45 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_actions + +import ( + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/cli" +) + +func Edge(args ...string) model.Action { + return &edge{ + args: args, + } +} + +func (a *edge) Execute(m *model.Model) error { + return EdgeExec(m, a.args...) +} + +type edge struct { + args []string +} + +func EdgeExec(m *model.Model, args ...string) error { + _, err := EdgeExecWithOutput(m, args...) + return err +} + +func EdgeExecWithOutput(m *model.Model, args ...string) (string, error) { + return cli.Exec(m, append([]string{"edge", "-i", model.ActiveInstanceId()}, args...)...) +} diff --git a/zititest/zitilab/actions/fabric_cli.go b/zititest/zitilab/actions/fabric_cli.go new file mode 100644 index 000000000..de58d771c --- /dev/null +++ b/zititest/zitilab/actions/fabric_cli.go @@ -0,0 +1,37 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_actions + +import ( + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab/cli" +) + +func Fabric(args ...string) model.Action { + return &fabric{ + args: args, + } +} + +func (a *fabric) Execute(m *model.Model) error { + _, err := cli.Exec(m, append([]string{"fabric", "-i", model.ActiveInstanceId()}, a.args...)...) + return err +} + +type fabric struct { + args []string +} diff --git a/zititest/zitilab/actions/logs.go b/zititest/zitilab/actions/logs.go new file mode 100644 index 000000000..33ab3857e --- /dev/null +++ b/zititest/zitilab/actions/logs.go @@ -0,0 +1,106 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_actions + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/foundation/v2/info" + "github.com/sirupsen/logrus" +) + +func Logs() model.Action { + return &logs{} +} + +func (self *logs) Execute(m *model.Model) error { + if !m.IsBound() { + return fmt.Errorf("model not bound") + } + + snapshot := fmt.Sprintf("%d", info.NowInMilliseconds()) + for rn, r := range m.Regions { + for hn, h := range r.Hosts { + ssh := lib.NewSshConfigFactory(h) + if err := self.forHost(snapshot, rn, hn, ssh); err != nil { + return fmt.Errorf("error retrieving logs for [%s/%s] (%w)", rn, hn, err) + } + } + } + return nil +} + +func (self *logs) forHost(snapshot, rn, hn string, ssh lib.SshConfigFactory) error { + path := filepath.Join(model.AllocateForensicScenario(snapshot, "logs"), rn, hn) + if err := os.MkdirAll(path, os.ModePerm); err != nil { + return fmt.Errorf("error creating logs path [%s] for host [%s/%s] (%w)", path, rn, hn, err) + } + logrus.Infof("=> [%s]", path) + + fis, err := lib.RemoteFileList(ssh, ".") + if err != nil { + return fmt.Errorf("error retrieving home directory for host [%s/%s] (%w)", rn, hn, err) + } + hasLogs := false + for _, fi := range fis { + if fi.Name() == "logs" && fi.IsDir() { + hasLogs = true + break + } + } + + if hasLogs { + if err := self.forHostDir(path, "logs", ssh); err != nil { + return fmt.Errorf("error retrieving files from host [%s/%s] (%w)", rn, hn, err) + } + } + + return nil +} + +func (self *logs) forHostDir(localPath, remotePath string, ssh lib.SshConfigFactory) error { + fis, err := lib.RemoteFileList(ssh, remotePath) + if err != nil { + return err + } + var paths []string + for _, fi := range fis { + if fi.IsDir() { + nextLocalPath := filepath.Join(localPath, fi.Name()) + if err := os.MkdirAll(nextLocalPath, os.ModePerm); err != nil { + return fmt.Errorf("error creating local path [%s] (%w)", nextLocalPath, err) + } + nextRemotePath := filepath.Join(remotePath, fi.Name()) + if err := self.forHostDir(nextLocalPath, nextRemotePath, ssh); err != nil { + return fmt.Errorf("error recursing into tree (%w)", err) + } + + } else { + paths = append(paths, filepath.Join(remotePath, fi.Name())) + } + } + if err := lib.RetrieveRemoteFiles(ssh, localPath, paths...); err != nil { + return fmt.Errorf("error retrieving from [%s] (%w)", localPath, err) + } + return nil +} + +type logs struct{} diff --git a/zititest/zitilab/actions/metricbeat.go b/zititest/zitilab/actions/metricbeat.go new file mode 100644 index 000000000..dd32156b1 --- /dev/null +++ b/zititest/zitilab/actions/metricbeat.go @@ -0,0 +1,39 @@ +package zitilib_actions + +import ( + "fmt" + + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" +) + +type metricbeatStart struct { + hostSpec string + configPath string + dataPath string + logPath string +} + +func StartMetricbeat(hostSpec, configPath, dataPath, logPath string) model.Action { + return &metricbeatStart{ + hostSpec: hostSpec, + configPath: configPath, + dataPath: dataPath, + logPath: logPath, + } +} + +func (mbs *metricbeatStart) Execute(m *model.Model) error { + return m.ForEachHost(mbs.hostSpec, 24, func(c *model.Host) error { + ssh := lib.NewSshConfigFactory(c) + + cmd := fmt.Sprintf("screen -d -m nohup metricbeat --path.config %s --path.data %s --path.logs %s 2>&1 &", mbs.configPath, mbs.dataPath, mbs.logPath) + + if output, err := lib.RemoteExec(ssh, cmd); err != nil { + logrus.Errorf("error starting metricbeat service [%s] (%v)", output, err) + return err + } + return nil + }) +} diff --git a/zititest/zitilab/bootstrap.go b/zititest/zitilab/bootstrap.go new file mode 100644 index 000000000..f0304e43f --- /dev/null +++ b/zititest/zitilab/bootstrap.go @@ -0,0 +1,131 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilab + +import ( + "fmt" + "os" + "os/exec" + "path" + + "github.com/openziti/fablab/kernel/model" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +type bootstrapWithFallbacks struct { + fns []model.BootstrapExtension +} + +func BootstrapWithFallbacks(boostrapFns ...model.BootstrapExtension) *bootstrapWithFallbacks { + return &bootstrapWithFallbacks{ + fns: boostrapFns, + } +} + +func (bootstrap *bootstrapWithFallbacks) Bootstrap(m *model.Model) (retErr error) { + var err error + defer func() { + if retErr == nil && err != nil { + logrus.WithError(err).Info("Bootstrap succeeded, but had to use a fallback") + } + }() + for _, f := range bootstrap.fns { + e := f.Bootstrap(m) + if e == nil { + return nil + } + if err == nil { + err = e + continue + } + err = errors.Wrap(err, e.Error()) + } + return err +} + +type BootstrapFromEnv struct{} + +func (bootstrap *BootstrapFromEnv) Bootstrap(m *model.Model) error { + logrus.Infof("Bootstraping from Env") + zitiRoot = os.Getenv("ZITI_ROOT") + if zitiRoot == "" { + if zitiPath, err := exec.LookPath("ziti"); err == nil { + zitiRoot = path.Dir(zitiPath) + } else { + return fmt.Errorf("ZITI_PATH not set and ziti executable not found in path. please set 'ZITI_ROOT'") + } + } + + if fi, err := os.Stat(zitiRoot); err == nil { + if !fi.IsDir() { + return fmt.Errorf("invalid 'ZITI_ROOT' (!directory)") + } + } else { + return fmt.Errorf("non-existent 'ZITI_ROOT', given %s", zitiRoot) + } + + logrus.Debugf("ZITI_ROOT = [%s]", zitiRoot) + + return nil +} + +type bootstrapFromDir struct { + sourcePath string + destPath string +} + +func BootstrapFromDir(sourcePath, destPath string) *bootstrapFromDir { + return &bootstrapFromDir{ + sourcePath: sourcePath, + destPath: destPath, + } +} + +func (b *bootstrapFromDir) Bootstrap(m *model.Model) error { + logrus.Infof("Bootstraping from Dir") + zitiRoot = b.sourcePath + if _, err := os.Stat(zitiRoot); err != nil { + return fmt.Errorf("non-existent 'ZITI_ROOT', given %s", zitiRoot) + } + logrus.Debugf("ZITI_ROOT = [%s]", zitiRoot) + + return nil +} + +type BootstrapFromFind struct{} + +func (bootstrap *BootstrapFromFind) Bootstrap(m *model.Model) error { + logrus.Infof("Bootstraping from Find") + if zitiPath, err := exec.LookPath("ziti"); err == nil { + zitiRoot = path.Dir(path.Dir(zitiPath)) + } else { + return fmt.Errorf("ZITI_PATH not set and ziti executable not found in path. please set 'ZITI_ROOT'") + } + + if fi, err := os.Stat(zitiRoot); err == nil { + if !fi.IsDir() { + return fmt.Errorf("invalid 'ZITI_ROOT' (!directory)") + } + } else { + return fmt.Errorf("non-existent 'ZITI_ROOT', given %s", zitiRoot) + } + + logrus.Debugf("ZITI_ROOT = [%s]", zitiRoot) + + return nil +} diff --git a/zititest/zitilab/cli/cli.go b/zititest/zitilab/cli/cli.go new file mode 100644 index 000000000..6b463884d --- /dev/null +++ b/zititest/zitilab/cli/cli.go @@ -0,0 +1,46 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cli + +import ( + "bytes" + "errors" + "os" + "strings" + + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/ziti/cmd" + "github.com/sirupsen/logrus" +) + +func Exec(m *model.Model, args ...string) (string, error) { + if !m.IsBound() { + return "", errors.New("model not bound") + } + + var cliOut bytes.Buffer + var cliErr bytes.Buffer + + ziticli := cmd.NewRootCommand(os.Stdin, &cliOut, &cliErr) + ziticli.SetArgs(args) + logrus.Infof("executing: %s", strings.Join(args, " ")) + if err := ziticli.Execute(); err != nil { + logrus.Errorf("err executing command, err:[%e]", err) + } + + return cliOut.String(), nil +} diff --git a/zititest/zitilab/console/action.go b/zititest/zitilab/console/action.go new file mode 100644 index 000000000..af506729a --- /dev/null +++ b/zititest/zitilab/console/action.go @@ -0,0 +1,45 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package console + +import ( + "embed" + "github.com/openziti/fablab/kernel/model" + "io/fs" + "net/http" +) + +//go:embed webroot +var webroot embed.FS + +func Console() model.Action { + return &console{} +} + +func (consoleAction *console) Execute(m *model.Model) error { + server := NewServer() + go server.Listen() + + unprefixedWebroot, err := fs.Sub(webroot, "webroot") + if err != nil { + return err + } + http.Handle("/", http.FileServer(http.FS(unprefixedWebroot))) + return http.ListenAndServe(":8080", nil) +} + +type console struct{} diff --git a/zititest/zitilab/console/client.go b/zititest/zitilab/console/client.go new file mode 100644 index 000000000..914a24486 --- /dev/null +++ b/zititest/zitilab/console/client.go @@ -0,0 +1,76 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package console + +import ( + "github.com/sirupsen/logrus" + "golang.org/x/net/websocket" +) + +func NewClient(ws *websocket.Conn, server *Server) *Client { + nextId++ + return &Client{ + id: nextId, + ws: ws, + server: server, + ch: make(chan *Message, chBufSize), + doneCh: make(chan struct{}), + } +} + +func (client *Client) Conn() *websocket.Conn { + return client.ws +} + +func (client *Client) Write(msg *Message) { + select { + case client.ch <- msg: + default: + } +} + +func (client *Client) Listen() { + client.listenWrite() +} + +func (client *Client) listenWrite() { + for { + select { + case msg := <-client.ch: + if err := websocket.JSON.Send(client.ws, msg); err != nil { + logrus.Errorf("error sending to client [#%d] (%v)", client.id, err) + } + + case <-client.doneCh: + client.server.Del(client) + close(client.doneCh) + return + } + } +} + +type Client struct { + id int + ws *websocket.Conn + server *Server + ch chan *Message + doneCh chan struct{} +} + +var nextId int = 0 + +const chBufSize = 100 diff --git a/zititest/zitilab/console/message.go b/zititest/zitilab/console/message.go new file mode 100644 index 000000000..8325f4578 --- /dev/null +++ b/zititest/zitilab/console/message.go @@ -0,0 +1,35 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package console + +type Message struct { + Source string `json:"source"` + Routers []string `json:"routers"` + Links []*Link `json:"links"` + Metrics []*Metric `json:"metrics"` +} + +type Link struct { + Id string `json:"id"` + Src string `json:"src"` + Dst string `json:"dst"` +} + +type Metric struct { + Key string `json:"key"` + Value string `json:"value"` +} diff --git a/zititest/zitilab/console/server.go b/zititest/zitilab/console/server.go new file mode 100644 index 000000000..793be794f --- /dev/null +++ b/zititest/zitilab/console/server.go @@ -0,0 +1,117 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package console + +import ( + "github.com/sirupsen/logrus" + "golang.org/x/net/websocket" + "net/http" +) + +func NewServer() *Server { + return &Server{ + clients: make(map[int]*Client), + addCh: make(chan *Client), + delCh: make(chan *Client), + sendAllCh: make(chan *Message), + doneCh: make(chan struct{}), + errCh: make(chan error), + routers: make(map[string]bool), + links: make(map[string]*Link), + } +} + +func (server *Server) Add(c *Client) { + server.addCh <- c +} + +func (server *Server) Del(c *Client) { + server.delCh <- c +} + +func (server *Server) Done() { + close(server.doneCh) +} + +func (server *Server) SendAll(msg *Message) { + server.sendAllCh <- msg +} + +func (server *Server) sendAll(msg *Message) { + for _, c := range server.clients { + c.Write(msg) + } +} + +func (server *Server) Listen() { + logrus.Infof("listening") + + onConnected := func(ws *websocket.Conn) { + defer func() { + if err := ws.Close(); err != nil { + server.errCh <- err + } + }() + + client := NewClient(ws, server) + server.Add(client) + client.Listen() + } + http.Handle("/metrics", websocket.Handler(onConnected)) + + for { + select { + case client := <-server.addCh: + server.clients[client.id] = client + server.sendNetwork(client) + + case client := <-server.delCh: + delete(server.clients, client.id) + + case msg := <-server.sendAllCh: + server.sendAll(msg) + + case err := <-server.errCh: + logrus.Errorf("error (%v)", err) + + case <-server.doneCh: + return + } + } +} + +func (server *Server) sendNetwork(c *Client) { + msg := &Message{} + for id := range server.routers { + msg.Routers = append(msg.Routers, id) + } + for _, link := range server.links { + msg.Links = append(msg.Links, link) + } + c.Write(msg) +} + +type Server struct { + clients map[int]*Client + addCh chan *Client + delCh chan *Client + sendAllCh chan *Message + doneCh chan struct{} + errCh chan error + routers map[string]bool + links map[string]*Link +} diff --git a/zititest/zitilab/console/webroot/index.html b/zititest/zitilab/console/webroot/index.html new file mode 100644 index 000000000..7122fa8ad --- /dev/null +++ b/zititest/zitilab/console/webroot/index.html @@ -0,0 +1,34 @@ + + + + + zitilib console + + + + + + + + + + + + + + diff --git a/zititest/zitilab/console/webroot/js/network.js b/zititest/zitilab/console/webroot/js/network.js new file mode 100644 index 000000000..2b243cfb1 --- /dev/null +++ b/zititest/zitilab/console/webroot/js/network.js @@ -0,0 +1,126 @@ +let width = window.innerWidth, + height = window.innerHeight; + +let network = { + "routers": [ + ], + "links": [ + ] +}; + +let svg = d3.select('body').append('svg') + .attr('width', width) + .attr('height', height); + +let nodes = network.routers, + links = network.links; + +let simulation = d3.forceSimulation(nodes) + .force('charge', d3.forceManyBody().strength(-2999)) + .force('center', d3.forceCenter(width / 2, height / 2)) + .force('link', d3.forceLink(links).distance(() => { return 360; })); + +function processMessage(msg) { + let networkChanged = false; + let deleteList; + if(msg.routers != null) { + console.log("merging routers", msg.routers); + msg.routers.forEach(id => { + if(!network.routers.find(o => o.id === id)) { + network.routers.push({"id": id, "x": 0, "y": 0}); + console.log("added router [" + id + "]"); + } + }); + deleteList = []; + network.routers.forEach(r => { + if(!msg.routers.find(o => o === r.id)) { + deleteList.push(r.id); + } + }); + deleteList.forEach(id => { + let i = network.routers.findIndex(v => v.id === id); + if(i > -1) { + network.routers.splice(i, 1); + console.log("removed router [" + id + "]"); + } + }); + console.log("networks.routers", network.routers); + networkChanged = true; + } + + if (msg.links != null) { + console.log("merging links", msg.links); + msg.links.forEach(l => { + if (!network.links.find(o => o.id === l.id)) { + src = network.routers.findIndex(r => r.id === l.src); + dst = network.routers.findIndex(r => r.id === l.dst); + if (src > -1 && dst > -1) { + network.links.push({"id": l.id, "source": src, "target": dst, "x": 0, "y": 0}); + console.log("added link [" + l.id + "]"); + } + } + }); + deleteList = []; + network.links.forEach(l => { + if (!msg.links.find(o => o.id === l.id)) { + deleteList.push(l.id); + } + }); + deleteList.forEach(id => { + let i = network.links.findIndex(v => v.id === id); + if (i > -1) { + network.links.splice(i, 1); + console.log("removed link [" + id + "]"); + } + }); + console.log("networks.links", network.links); + + networkChanged = true; + } + + if (msg.metrics != null) { + console.log("source", msg.source, "metrics", msg.metrics); + } + + if(networkChanged) { + updateSimulation(); + } +} + +function updateSimulation() { + let linkElements = svg.selectAll('line').data(links, link => link.id); + linkElements.exit().remove(); + let linkEnter = linkElements.enter().append('line').attr('class', 'link'); + linkElements = linkElements.merge(linkEnter); + + let nodeElements = svg.selectAll('circle').data(nodes); + nodeElements.exit().remove(); + let nodeEnter = nodeElements.enter().append('circle').attr('r', 25).attr('class', 'node'); + nodeElements = nodeElements.merge(nodeEnter); + nodeElements.raise(); + + let textElements = svg.selectAll('text').data(nodes); + textElements.exit().remove(); + let textEnter = textElements.enter() + .append('text') + .text(node => node.id) + .attr('dx', 0) + .attr('dy', 0) + .attr('class', 'node-label'); + textElements = textElements.merge(textEnter); + textElements.raise(); + + simulation.nodes(nodes).on('tick', () => { + nodeElements.attr('cx', node => node.x).attr('cy', node => node.y); + textElements.attr('x', node => node.x).attr('y', node => node.y); + linkElements + .attr('x1', link => link.source.x) + .attr('y1', link => link.source.y) + .attr('x2', link => link.target.x) + .attr('y2', link => link.target.y); + }); + simulation.force('link').links(network.links); + simulation.alpha(1).restart(); +} + +updateSimulation(); \ No newline at end of file diff --git a/zititest/zitilab/console/webroot/js/ws.js b/zititest/zitilab/console/webroot/js/ws.js new file mode 100644 index 000000000..9b72ee66f --- /dev/null +++ b/zititest/zitilab/console/webroot/js/ws.js @@ -0,0 +1,26 @@ +var webSocket; + +function openWebSocket() { + if (webSocket !== undefined && webSocket.readyState !== WebSocket.CLOSED) { + return; + } + webSocket = new WebSocket("ws://localhost:8080/metrics"); + + webSocket.onmessage = function (event) { + let msg = $.parseJSON(event.data); + processMessage(msg); + }; + + webSocket.onclose = function (event) { + console.log("connection closed"); + }; +} + +$(window).on('beforeunload', function(){ + webSocket.close(); + console.log("closed websocket"); +}); + +(function () { + openWebSocket(); +})(); \ No newline at end of file diff --git a/zititest/zitilab/models/consts.go b/zititest/zitilab/models/consts.go new file mode 100644 index 000000000..b26e5bee0 --- /dev/null +++ b/zititest/zitilab/models/consts.go @@ -0,0 +1,22 @@ +package models + +const ( + RemoteId = "#remote" + LocalId = "#local" + + ServiceTag = ".service" + ClientTag = ".client" + + ControllerTag = ".ctrl" + RouterTag = ".router" + EdgeRouterTag = ".edge-router" + SdkAppTag = ".sdk-app" + + LoopListenerTag = ".loop-listener" + LoopDialerTag = ".loop-dialer" + + TerminatorTag = ".terminator" + + HasControllerComponent = "component.ctrl" + HasRouterComponent = "component.router" +) diff --git a/zititest/zitilab/models/db_builder.go b/zititest/zitilab/models/db_builder.go new file mode 100644 index 000000000..2d52b1204 --- /dev/null +++ b/zititest/zitilab/models/db_builder.go @@ -0,0 +1,137 @@ +package models + +import ( + "fmt" + "github.com/openziti/edge/controller/persistence" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fabric/controller/db" + "github.com/openziti/fabric/controller/network" + "github.com/openziti/storage/boltz" + "github.com/pkg/errors" + "go.etcd.io/bbolt" + "strings" +) + +type ZitiDbBuilderStrategy interface { + GetDbFile() string + GetSite(router *persistence.EdgeRouter) (string, bool) + PostProcess(router *persistence.EdgeRouter, c *model.Component) +} + +type ZitiDbBuilder struct { + Strategy ZitiDbBuilderStrategy +} + +type dbProvider struct { + zitiDb boltz.Db + stores *db.Stores +} + +func (self *dbProvider) GetDb() boltz.Db { + return self.zitiDb +} + +func (self *dbProvider) GetStores() *db.Stores { + return self.stores +} + +func (self *dbProvider) GetManagers() *network.Managers { + panic("should not be needed") +} + +func (self *ZitiDbBuilder) Build(m *model.Model) error { + dbFile := self.Strategy.GetDbFile() + zitiDb, err := db.Open(dbFile) + if err != nil { + return errors.Wrapf(err, "unable to open ziti bbolt db [%v]", dbFile) + } + + defer func() { + if err = zitiDb.Close(); err != nil { + panic(err) + } + }() + + fabricStore, err := db.InitStores(zitiDb) + if err != nil { + return errors.Wrapf(err, "unable to init fabric stores using db [%v]", dbFile) + } + + provider := &dbProvider{ + zitiDb: zitiDb, + stores: fabricStore, + } + + edgeStores, err := persistence.NewBoltStores(provider) + if err != nil { + return errors.Wrapf(err, "unable to init edge stores using db [%v]", dbFile) + } + + err = zitiDb.View(func(tx *bbolt.Tx) error { + ids, _, err := edgeStores.EdgeRouter.QueryIds(tx, "true limit none") + if err != nil { + return err + } + + for _, id := range ids { + er, err := edgeStores.EdgeRouter.LoadOneById(tx, id) + if err != nil { + return err + } + + if site, useEdgeRouter := self.Strategy.GetSite(er); useEdgeRouter { + regionId := site[:len(site)-1] + + var region *model.Region + for _, r := range m.Regions { + if r.Site == site { + region = r + break + } + } + + if region == nil { + if _, found := m.Regions[site]; found { + return errors.Errorf("trying to add region for site %v, but one exists, with different site", site) + } + region = &model.Region{ + Scope: model.Scope{Tags: model.Tags{}}, + Region: regionId, + Site: site, + Hosts: model.Hosts{}, + } + m.Regions[site] = region + } + + host := &model.Host{ + Scope: model.Scope{Tags: model.Tags{}}, + Region: region, + Components: model.Components{}, + } + id := strings.ReplaceAll(er.Id, ".", "_") + region.Hosts["router_"+id] = host + + component := &model.Component{ + Scope: model.Scope{Tags: model.Tags{}}, + ConfigSrc: "router.yml", + ConfigName: fmt.Sprintf("router-%v.yml", er.Id), + BinaryName: "ziti router", + Host: host, + } + + host.Components[er.Id] = component + self.Strategy.PostProcess(er, component) + } + } + return nil + }) + + return err +} + +func (self *ZitiDbBuilder) DefaultGetSite(er *persistence.EdgeRouter) (string, bool) { + if val, found := er.Tags["fablab.site"]; found { + return fmt.Sprintf("%v", val), true + } + return "", false +} diff --git a/zititest/zitilab/paths.go b/zititest/zitilab/paths.go new file mode 100644 index 000000000..a444c599d --- /dev/null +++ b/zititest/zitilab/paths.go @@ -0,0 +1,38 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilab + +import ( + "github.com/openziti/fablab/kernel/lib/runlevel/2_kitting/devkit" + "github.com/openziti/fablab/kernel/model" +) + +func ZitiRoot() string { + return zitiRoot +} + +func DefaultZitiBinaries() model.ConfigurationStage { + zitiBinaries := []string{ + "ziti", + "ziti-controller", + "ziti-router", + } + + return devkit.DevKitF(ZitiRoot, zitiBinaries) +} + +var zitiRoot string diff --git a/zititest/zitilab/runlevel/0_infrastructure/consul.go b/zititest/zitilab/runlevel/0_infrastructure/consul.go new file mode 100644 index 000000000..eb4407683 --- /dev/null +++ b/zititest/zitilab/runlevel/0_infrastructure/consul.go @@ -0,0 +1,41 @@ +package zitilib_runlevel_0_infrastructure + +import ( + "fmt" + + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" +) + +type installConsul struct { + hostSpec string +} + +func InstallConsul(hostSpec string) model.InfrastructureStage { + return &installConsul{ + hostSpec: hostSpec, + } +} + +func (imb *installConsul) Express(run model.Run) error { + return run.GetModel().ForEachHost(imb.hostSpec, 25, func(host *model.Host) error { + ssh := lib.NewSshConfigFactory(host) + + if output, err := lib.RemoteExec(ssh, "curl --fail --silent --show-error --location https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/hashicorp-archive-keyring.gpg"); err != nil { + return fmt.Errorf("error getting hashicorp gpg key on host [%s] %s (%s)", host.PublicIp, output, err) + } + + if output, err := lib.RemoteExec(ssh, "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee -a /etc/apt/sources.list.d/hashicorp.list"); err != nil { + return fmt.Errorf("error adding hashicorp repo to apt on host [%s] %s (%s)", host.PublicIp, output, err) + } + + cmd := "sudo apt-get update && sudo apt-get install consul -y" + + if output, err := lib.RemoteExec(ssh, cmd); err != nil { + return fmt.Errorf("error installing Consul on host [%s] %s (%s)", host.PublicIp, output, err) + } + logrus.Infof("%s => %s", host.PublicIp, "installing Consul") + return nil + }) +} diff --git a/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go b/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go new file mode 100644 index 000000000..9fa68ca09 --- /dev/null +++ b/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go @@ -0,0 +1,50 @@ +package zitilib_runlevel_0_infrastructure + +import ( + "fmt" + + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" +) + +const RECCOMENDED_METRICBEAT_VERSION = "8.3.2" + +type installMetricbeat struct { + hostSpec string + version string +} + +func InstallMetricbeat(hostSpec, version string) model.InfrastructureStage { + return &installMetricbeat{ + hostSpec: hostSpec, + version: version, + } +} + +func (imb *installMetricbeat) Express(run model.Run) error { + return run.GetModel().ForEachHost(imb.hostSpec, 25, func(host *model.Host) error { + ssh := lib.NewSshConfigFactory(host) + + if output, err := lib.RemoteExec(ssh, "wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -"); err != nil { + return fmt.Errorf("error getting elastic gpg key on host [%s] %s (%s)", host.PublicIp, output, err) + } + + if output, err := lib.RemoteExec(ssh, "echo \"deb https://artifacts.elastic.co/packages/8.x/apt stable main\" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list"); err != nil { + return fmt.Errorf("error adding elastic repo to apt on host [%s] %s (%s)", host.PublicIp, output, err) + } + + cmd := fmt.Sprintf("sudo apt-get update && sudo apt-get install metricbeat%s -y", func() string { + if imb.version != "" { + return fmt.Sprintf("=%s", imb.version) + } + return "" + }()) + + if output, err := lib.RemoteExec(ssh, cmd); err != nil { + return fmt.Errorf("error installing metricbeat on host [%s] %s (%s)", host.PublicIp, output, err) + } + logrus.Infof("%s => %s", host.PublicIp, "installing metricbeat") + return nil + }) +} diff --git a/zititest/zitilab/runlevel/1_configuration/cert.go b/zititest/zitilab/runlevel/1_configuration/cert.go new file mode 100644 index 000000000..8ebfc9783 --- /dev/null +++ b/zititest/zitilab/runlevel/1_configuration/cert.go @@ -0,0 +1,93 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_1_configuration + +import ( + "bytes" + "fmt" + "strings" + + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/ziti/cmd" + "github.com/sirupsen/logrus" +) + +func generateCa(trustDomain string) error { + if caExists, err := hasExistingCA("root"); caExists || err != nil { + return err + } + + var pkiOut bytes.Buffer + var pkiErr bytes.Buffer + ziticli := cmd.NewRootCommand(nil, &pkiOut, &pkiErr) + args := []string{"pki", "create", "ca", "--pki-root", model.PkiBuild(), "--ca-name", "root", "--ca-file", "root", "--trust-domain", trustDomain, "--"} + ziticli.SetArgs(args) + logrus.Infof("%v", args) + if err := ziticli.Execute(); err != nil { + logrus.Errorf("stdOut [%s], stdErr [%s]", strings.Trim(pkiOut.String(), " \t\r\n"), strings.Trim(pkiErr.String(), " \t\r\n")) + return fmt.Errorf("error generating key (%s)", err) + } + + return nil +} + +func generateSigningCert(name string) error { + logrus.Infof("generating signing certificate [%s]", name) + + var pkiOut bytes.Buffer + var pkiErr bytes.Buffer + + ziticli := cmd.NewRootCommand(nil, &pkiOut, &pkiErr) + + args := []string{"pki", "create", "intermediate", "--pki-root", model.PkiBuild(), "--ca-name", "root", + "--intermediate-file", name, "--intermediate-name", name + " signing cert"} + ziticli.SetArgs(args) + logrus.Infof("%v", args) + if err := ziticli.Execute(); err != nil { + logrus.Errorf("stdOut [%s], stdErr [%s]", strings.Trim(pkiOut.String(), " \t\r\n"), strings.Trim(pkiErr.String(), " \t\r\n")) + return fmt.Errorf("error generating key (%s)", err) + } + return nil +} + +func generateCert(name, ip, spiffeId string) error { + logrus.Infof("generating server certificate [%s:%s]", name, ip) + + var pkiOut bytes.Buffer + var pkiErr bytes.Buffer + ziticli := cmd.NewRootCommand(nil, &pkiOut, &pkiErr) + + args := []string{"pki", "create", "server", + "--server-name", name, + "--pki-root", model.PkiBuild(), + "--ca-name", name, + "--server-file", fmt.Sprintf("%s-server", name), + "--ip", ip} + + if spiffeId != "" { + args = append(args, "--spiffe-id", spiffeId) + } + + logrus.Infof("%v", args) + ziticli.SetArgs(args) + if err := ziticli.Execute(); err != nil { + logrus.Errorf("stdOut [%s], stdErr [%s]", strings.Trim(pkiOut.String(), " \t\r\n"), strings.Trim(pkiErr.String(), " \t\r\n")) + return fmt.Errorf("error generating server certificate (%s)", err) + } + + return nil +} diff --git a/zititest/zitilab/runlevel/1_configuration/fabric.go b/zititest/zitilab/runlevel/1_configuration/fabric.go new file mode 100644 index 000000000..56ef33ccb --- /dev/null +++ b/zititest/zitilab/runlevel/1_configuration/fabric.go @@ -0,0 +1,176 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_1_configuration + +import ( + "fmt" + "github.com/openziti/fablab/kernel/model" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + "os" + "path" + "strings" +) + +func Fabric(trustDomain string, componentSpecs ...string) model.ConfigurationStage { + if len(componentSpecs) == 0 { + componentSpecs = []string{"*"} + } + return &fabric{ + trustDomain: trustDomain, + componentSpecs: componentSpecs, + } +} + +type fabric struct { + trustDomain string + componentSpecs []string +} + +func (f *fabric) getSpiffeId(c *model.Component, id string) string { + for _, tag := range c.Tags { + if strings.HasPrefix(tag, "spiffe:") { + prefix := tag[len("spiffe:"):] + return prefix + "/" + id + } + } + return id +} + +func (f *fabric) Configure(run model.Run) error { + m := run.GetModel() + if err := generateCa(f.trustDomain); err != nil { + return fmt.Errorf("error generating ca (%s)", err) + } + + ips := map[string]string{} + + processedComponents := map[*model.Component]struct{}{} + + for _, spec := range f.componentSpecs { + for _, component := range m.SelectComponents(spec) { + if _, found := processedComponents[component]; found { + continue + } + processedComponents[component] = struct{}{} + + if component.PublicIdentity != "" { + logrus.Infof("generating public ip identity [%s/%s] on [%s/%s]", component.Id, component.PublicIdentity, component.Region().Id, component.Host.Id) + if err := generateSigningCert(component.PublicIdentity); err != nil { + return errors.Wrapf(err, "error generating public identity [%s/%s]", component.Id, component.PublicIdentity) + } + + if err := generateCert(component.PublicIdentity, component.Host.PublicIp, f.getSpiffeId(component, component.PublicIdentity)); err != nil { + return fmt.Errorf("error generating public identity [%s/%s]", component.Id, component.PublicIdentity) + } + + ips[component.GetPathId()+".public"] = component.Host.PublicIp + } + + if component.PrivateIdentity != "" { + logrus.Infof("generating private ip identity [%s/%s] on [%s/%s]", component.Id, component.PrivateIdentity, component.Region().Id, component.Host.Id) + if err := generateSigningCert(component.PrivateIdentity); err != nil { + return errors.Wrapf(err, "error generating private identity [%s/%s]", component.Id, component.PublicIdentity) + } + + if err := generateCert(component.PrivateIdentity, component.Host.PrivateIp, f.getSpiffeId(component, component.PrivateIdentity)); err != nil { + return fmt.Errorf("error generating private identity [%s/%s]", component.Id, component.PrivateIdentity) + } + ips[component.GetPathId()+".private"] = component.Host.PrivateIp + } + } + } + + return storeIps(ips) +} + +func haveIpsChanged(m *model.Model) (bool, error) { + ipFile := path.Join(model.PkiBuild(), "ips") + ips := map[string]string{} + if _, err := os.Stat(ipFile); err == nil { + ipData, err := os.ReadFile(ipFile) + if err != nil { + return false, err + } + if err = yaml.Unmarshal(ipData, &ips); err != nil { + return false, err + } + } + + for _, c := range m.SelectComponents("*") { + pubIdKey := c.GetPathId() + ".public" + if c.PublicIdentity != "" { + if ip, found := ips[pubIdKey]; found { + if ip == c.Host.PublicIp { + delete(ips, pubIdKey) + } else { + logrus.Infof("public ip for %v/%v has changed from %v -> %v. rebuilding pki", c.Id, c.PublicIdentity, c.Host.PublicIp, ip) + return true, nil + } + } else { + logrus.Infof("missing cert public identity of %v/%v. rebuilding pki", c.Id, c.PublicIdentity) + return true, nil + } + } + + privIdKey := c.GetPathId() + ".private" + if c.PrivateIdentity != "" { + if ip, found := ips[privIdKey]; found { + if ip == c.Host.PrivateIp { + delete(ips, privIdKey) + } else { + logrus.Infof("private ip for %v/%v has changed from %v -> %v. rebuilding pki", c.Id, c.PrivateIdentity, c.Host.PrivateIp, ip) + return true, nil + } + } else { + logrus.Infof("missing cert for private identity of %v/%v. rebuilding pki", c.Id, c.PrivateIdentity) + } + } + } + + return false, nil +} + +func storeIps(ips map[string]string) error { + ipFile := path.Join(model.PkiBuild(), "ips") + data, err := yaml.Marshal(ips) + if err != nil { + return err + } + return os.WriteFile(ipFile, data, 0600) +} + +func hasExisitingPki() (bool, error) { + if _, err := os.Stat(model.PkiBuild()); err != nil { + if os.IsNotExist(err) { + return false, nil + } + return true, err + } + return true, nil +} + +func hasExistingCA(name string) (bool, error) { + if _, err := os.Stat(path.Join(model.PkiBuild(), name)); err != nil { + if os.IsNotExist(err) { + return false, nil + } + return true, err + } + return true, nil +} diff --git a/zititest/zitilab/runlevel/1_configuration/if_no_pki.go b/zititest/zitilab/runlevel/1_configuration/if_no_pki.go new file mode 100644 index 000000000..6cc74ea73 --- /dev/null +++ b/zititest/zitilab/runlevel/1_configuration/if_no_pki.go @@ -0,0 +1,50 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_1_configuration + +import ( + "fmt" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" +) + +func IfNoPki(stages ...model.ConfigurationStage) model.ConfigurationStage { + return &ifNoPki{stages: stages} +} + +func (self *ifNoPki) Configure(run model.Run) error { + if existing, err := hasExisitingPki(); err == nil { + if existing { + logrus.Infof("skipping configuration. existing pki system at [%s]", model.PkiBuild()) + return nil + } + } else { + return fmt.Errorf("error checking pki existence at [%s] (%s)", model.PkiBuild(), err) + } + + for _, stage := range self.stages { + if err := stage.Configure(run); err != nil { + return fmt.Errorf("error running configuration stage (%w)", err) + } + } + + return nil +} + +type ifNoPki struct { + stages []model.ConfigurationStage +} diff --git a/zititest/zitilab/runlevel/1_configuration/if_pki_needs_refresh.go b/zititest/zitilab/runlevel/1_configuration/if_pki_needs_refresh.go new file mode 100644 index 000000000..19c7bc4e4 --- /dev/null +++ b/zititest/zitilab/runlevel/1_configuration/if_pki_needs_refresh.go @@ -0,0 +1,51 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_1_configuration + +import ( + "fmt" + "github.com/openziti/fablab/kernel/model" + "os" +) + +func IfPkiNeedsRefresh(stages ...model.ConfigurationStage) model.ConfigurationStage { + return &ifPkiNeedsRefresh{stages: stages} +} + +func (self *ifPkiNeedsRefresh) Configure(run model.Run) error { + if changed, err := haveIpsChanged(run.GetModel()); err != nil || !changed { + return err + } + + if existing, err := hasExisitingPki(); err == nil && existing { + if err = os.RemoveAll(model.PkiBuild()); err != nil { + return err + } + } + + for _, stage := range self.stages { + if err := stage.Configure(run); err != nil { + return fmt.Errorf("error running configuration stage (%w)", err) + } + } + + return nil +} + +type ifPkiNeedsRefresh struct { + stages []model.ConfigurationStage +} diff --git a/zititest/zitilab/runlevel/5_operation/circuit_metrics.go b/zititest/zitilab/runlevel/5_operation/circuit_metrics.go new file mode 100644 index 000000000..469fc67d7 --- /dev/null +++ b/zititest/zitilab/runlevel/5_operation/circuit_metrics.go @@ -0,0 +1,185 @@ +package zitilib_runlevel_5_operation + +import ( + "encoding/json" + "github.com/Jeffail/gabs/v2" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/channel/v2" + "github.com/openziti/channel/v2/protobufs" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fabric/event" + "github.com/openziti/fabric/pb/mgmt_pb" + "github.com/openziti/ziti/ziti/cmd/api" + "github.com/sirupsen/logrus" + "time" +) + +func CircuitMetrics(pollFreq time.Duration, closer <-chan struct{}, f func(string) string) model.OperatingStage { + return &circuitMetrics{ + closer: closer, + circuits: map[string]struct{}{}, + eventC: make(chan func(), 10), + pollFreq: pollFreq, + idToSelectorMapper: f, + } +} + +type circuitMetrics struct { + ch channel.Channel + model *model.Model + eventC chan func() + closer <-chan struct{} + circuits map[string]struct{} + pollFreq time.Duration + idToSelectorMapper func(string) string +} + +func (self *circuitMetrics) Operate(run model.Run) error { + self.model = run.GetModel() + bindHandler := func(binding channel.Binding) error { + binding.AddReceiveHandler(int32(mgmt_pb.ContentType_StreamEventsEventType), channel.ReceiveHandlerF(self.receiveCircuitEvents)) + binding.AddReceiveHandler(int32(mgmt_pb.ContentType_InspectResponseType), channel.ReceiveHandlerF(self.receiveCircuitInspectResults)) + return nil + } + + ch, err := api.NewWsMgmtChannel(channel.BindHandlerF(bindHandler)) + if err != nil { + panic(err) + } + self.ch = ch + + streamEventsRequest := map[string]interface{}{ + "format": "json", + "subscriptions": []*event.Subscription{{Type: event.CircuitEventsNs}}, + } + + msgBytes, err := json.Marshal(streamEventsRequest) + if err != nil { + return err + } + + requestMsg := channel.NewMessage(int32(mgmt_pb.ContentType_StreamEventsRequestType), msgBytes) + if err = requestMsg.WithTimeout(5 * time.Second).SendAndWaitForWire(ch); err != nil { + return err + } + go self.runMetrics() + return nil +} + +func (self *circuitMetrics) receiveCircuitEvents(msg *channel.Message, _ channel.Channel) { + log := pfxlog.Logger() + circuitEvent := &event.CircuitEvent{} + err := json.Unmarshal(msg.Body, &circuitEvent) + if err != nil { + panic(err) + } + + if circuitEvent.EventType == event.CircuitDeleted { + self.eventC <- func() { + delete(self.circuits, circuitEvent.CircuitId) + log.Infof("circuit removed: %v", circuitEvent.CircuitId) + } + } else if circuitEvent.EventType == event.CircuitCreated { + self.eventC <- func() { + self.circuits[circuitEvent.CircuitId] = struct{}{} + log.Infof("circuit added: %v, path: %v", circuitEvent.CircuitId, circuitEvent.Path) + } + } else if circuitEvent.EventType == event.CircuitUpdated { + log.Infof("circuit updated: %v, path: %v", circuitEvent.CircuitId, circuitEvent.Path) + } +} + +func (self *circuitMetrics) receiveCircuitInspectResults(msg *channel.Message, _ channel.Channel) { + log := pfxlog.Logger() + response := &mgmt_pb.InspectResponse{} + if err := protobufs.TypedResponse(response).Unmarshall(msg, nil); err != nil { + log.WithError(err).Error("error unmarshalling inspect response") + return + } + + for _, errStr := range response.Errors { + pfxlog.Logger().WithField(logrus.ErrorKey, errStr).Error("error reported by inspect") + } + + for _, val := range response.Values { + c, err := gabs.ParseJSON([]byte(val.Value)) + if err != nil { + log.WithError(err).Errorf("unable to parse inspect JSON: %v", val.Value) + } else { + self.ingestCircuitMetrics(val.AppId, api.Wrap2(c)) + } + } +} + +func (self *circuitMetrics) runMetrics() { + logrus.Infof("starting") + defer logrus.Infof("exiting") + + ticker := time.NewTicker(self.pollFreq) + defer ticker.Stop() + + for { + select { + case <-self.closer: + _ = self.ch.Close() + return + case evt := <-self.eventC: + evt() + case <-ticker.C: + self.requestCircuitMetrics() + } + } +} + +func (self *circuitMetrics) requestCircuitMetrics() { + if len(self.circuits) > 0 { + inspectRequest := &mgmt_pb.InspectRequest{} + for circuitId := range self.circuits { + inspectRequest.RequestedValues = append(inspectRequest.RequestedValues, "circuit:"+circuitId) + } + if err := protobufs.MarshalTyped(inspectRequest).Send(self.ch); err != nil { + pfxlog.Logger().WithError(err).Error("failed to send circuit inspect request") + } + } +} + +func (self *circuitMetrics) ingestCircuitMetrics(sourceId string, circuitDetail *api.Gabs2Wrapper) { + log := pfxlog.Logger() + circuitId := circuitDetail.String("circuitId") + xgDetails := circuitDetail.Path("xgressDetails") + if xgDetails == nil { + return + } + for _, child := range xgDetails.ChildrenMap() { + xg := api.Wrap2(child) + modelEvent := &model.MetricsEvent{ + Timestamp: time.Now(), + Metrics: model.MetricSet{}, + Tags: map[string]string{ + "circuitId": circuitId, + "originator": xg.String("originator"), + }, + } + + if sendBufferDetail := xg.Path("sendBufferDetail"); sendBufferDetail != nil { + for k, val := range sendBufferDetail.ChildrenMap() { + modelEvent.Metrics["circuit.sendBuffer."+k] = val.Data() + } + } + + if recvBufferDetail := xg.Path("recvBufferDetail"); recvBufferDetail != nil { + for k, val := range recvBufferDetail.ChildrenMap() { + modelEvent.Metrics["circuit.recvBuffer."+k] = val.Data() + } + } + + hostSelector := self.idToSelectorMapper(sourceId) + host, err := self.model.SelectHost(hostSelector) + if err == nil { + self.model.AcceptHostMetrics(host, modelEvent) + log.Infof("<$= [%s/%v]", sourceId, circuitId) + } else { + log.WithError(err).Error("circuitMetrics: unable to find host") + } + } +} diff --git a/zititest/zitilab/runlevel/5_operation/client_metrics.go b/zititest/zitilab/runlevel/5_operation/client_metrics.go new file mode 100644 index 000000000..9e422d245 --- /dev/null +++ b/zititest/zitilab/runlevel/5_operation/client_metrics.go @@ -0,0 +1,178 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_5_operation + +import ( + "encoding/binary" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fabric/pb/mgmt_pb" + "github.com/openziti/sdk-golang/ziti" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/cli" + "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" + "io" + "net" + "time" +) + +func NewClientMetrics(service string, closer <-chan struct{}) *ClientMetrics { + return NewClientMetricsWithIdMapper(service, closer, func(id string) string { + return "#" + id + }) +} + +func NewClientMetricsWithIdMapper(service string, closer <-chan struct{}, f func(string) string) *ClientMetrics { + return &ClientMetrics{ + service: service, + closer: closer, + idToSelectorMapper: f, + } +} + +type ClientMetrics struct { + service string + listener net.Listener + closer <-chan struct{} + model *model.Model + idToSelectorMapper func(string) string +} + +func (metrics *ClientMetrics) Activate(run model.Run) error { + if err := zitilib_actions.EdgeExec(run.GetModel(), "delete", "identity", "metrics-host"); err != nil { + return err + } + + jwtFilePath := run.GetLabel().GetFilePath("metrics-host.jwt") + if err := zitilib_actions.EdgeExec(run.GetModel(), "create", "identity", "service", "metrics-host", "-a", "metrics-host", "-o", jwtFilePath); err != nil { + return err + } + + identityConfigPath := run.GetLabel().GetFilePath("metrics-host.json") + if _, err := cli.Exec(run.GetModel(), "edge", "enroll", jwtFilePath, "-o", identityConfigPath); err != nil { + return err + } + + return nil +} + +func (metrics *ClientMetrics) Operate(run model.Run) error { + metrics.model = run.GetModel() + + identityConfigPath := run.GetLabel().GetFilePath("metrics-host.json") + + context, err := ziti.NewContextFromFile(identityConfigPath) + if err != nil { + return err + } + + listener, err := context.Listen(metrics.service) + if err != nil { + return err + } + + metrics.listener = listener + + go func() { + for { + conn, err := listener.Accept() + if err != nil { + pfxlog.Logger().WithError(err).Info("metrics listener closed, returning") + return + } + go metrics.HandleMetricsConn(conn) + } + }() + + go metrics.runMetrics() + + return nil +} + +func (metrics *ClientMetrics) HandleMetricsConn(conn net.Conn) { + defer func() { _ = conn.Close() }() + + log := pfxlog.Logger() + log.Infof("new client metrics connection established from: %v", conn.RemoteAddr().String()) + lenBuf := make([]byte, 4) + msgBuf := make([]byte, 4*1024) + for { + if _, err := io.ReadFull(conn, lenBuf); err != nil { + log.WithError(err).Info("metrics conn closed, exiting read loop") + return + } + msgLen := int(binary.LittleEndian.Uint32(lenBuf)) + if msgLen > 1024*16 { + log.Errorf("got invalid metrics message len: %v, closing connection", msgLen) + return + } + + if msgLen > len(msgBuf) { + msgBuf = make([]byte, msgLen) + } + + if _, err := io.ReadFull(conn, msgBuf[:msgLen]); err != nil { + pfxlog.Logger().WithError(err).Info("metrics conn closed, exiting read loop") + return + } + + event := &mgmt_pb.StreamMetricsEvent{} + err := proto.Unmarshal(msgBuf[:msgLen], event) + if err != nil { + log.WithError(err).Error("error handling metrics receive, exiting") + return + } + + hostSelector := metrics.idToSelectorMapper(event.SourceId) + host, err := metrics.model.SelectHost(hostSelector) + if err == nil { + modelEvent := metrics.toClientMetricsEvent(event) + metrics.model.AcceptHostMetrics(host, modelEvent) + log.Infof("<$= [%s]", event.SourceId) + } else { + log.WithError(err).Error("clientMetrics: unable to find host") + } + } +} + +func (metrics *ClientMetrics) runMetrics() { + logrus.Infof("starting") + defer logrus.Infof("exiting") + + <-metrics.closer + _ = metrics.listener.Close() +} + +func (metrics *ClientMetrics) toClientMetricsEvent(fabricEvent *mgmt_pb.StreamMetricsEvent) *model.MetricsEvent { + modelEvent := &model.MetricsEvent{ + Timestamp: time.Unix(fabricEvent.Timestamp.Seconds, int64(fabricEvent.Timestamp.Nanos)), + Metrics: model.MetricSet{}, + } + + for name, val := range fabricEvent.IntMetrics { + group := fabricEvent.MetricGroup[name] + modelEvent.Metrics.AddGroupedMetric(group, name, val) + } + + for name, val := range fabricEvent.FloatMetrics { + group := fabricEvent.MetricGroup[name] + modelEvent.Metrics.AddGroupedMetric(group, name, val) + } + + return modelEvent +} diff --git a/zititest/zitilab/runlevel/5_operation/loop_dialer.go b/zititest/zitilab/runlevel/5_operation/loop_dialer.go new file mode 100644 index 000000000..964a9e9d8 --- /dev/null +++ b/zititest/zitilab/runlevel/5_operation/loop_dialer.go @@ -0,0 +1,83 @@ +/* + Copyright 2020 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_5_operation + +import ( + "fmt" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" + "strings" +) + +func Loop3Dialer(host *model.Host, scenario, endpoint string, joiner chan struct{}, extraArgs ...string) model.OperatingStage { + return &loopDialer{ + host: host, + scenario: scenario, + endpoint: endpoint, + joiner: joiner, + subcmd: "loop3", + extraArgs: extraArgs, + } +} + +func LoopDialer(host *model.Host, scenario, endpoint string, joiner chan struct{}, extraArgs ...string) model.OperatingStage { + return &loopDialer{ + host: host, + scenario: scenario, + endpoint: endpoint, + joiner: joiner, + subcmd: "loop2", + extraArgs: extraArgs, + } +} + +func (self *loopDialer) Operate(run model.Run) error { + ssh := lib.NewSshConfigFactory(self.host) + if err := lib.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v dialer", self.subcmd)); err != nil { + return fmt.Errorf("error killing %v listeners (%w)", self.subcmd, err) + } + + go self.run(run) + return nil +} + +func (self *loopDialer) run(ctx model.Run) { + defer func() { + if self.joiner != nil { + close(self.joiner) + logrus.Debugf("closed joiner") + } + }() + + ssh := lib.NewSshConfigFactory(self.host) + logFile := fmt.Sprintf("/home/%s/logs/%v-dialer-%s.log", ssh.User(), self.subcmd, ctx.GetId()) + dialerCmd := fmt.Sprintf("/home/%s/fablab/bin/ziti-fabric-test %v dialer /home/%s/fablab/cfg/%s -e %s -s %s %s >> %s 2>&1", + ssh.User(), self.subcmd, ssh.User(), self.scenario, self.endpoint, self.host.GetId(), strings.Join(self.extraArgs, " "), logFile) + if output, err := lib.RemoteExec(ssh, dialerCmd); err != nil { + logrus.Errorf("error starting loop dialer [%s] (%v)", output, err) + } +} + +type loopDialer struct { + host *model.Host + endpoint string + scenario string + joiner chan struct{} + subcmd string + extraArgs []string +} diff --git a/zititest/zitilab/runlevel/5_operation/loop_listener.go b/zititest/zitilab/runlevel/5_operation/loop_listener.go new file mode 100644 index 000000000..83d93655f --- /dev/null +++ b/zititest/zitilab/runlevel/5_operation/loop_listener.go @@ -0,0 +1,65 @@ +package zitilib_runlevel_5_operation + +import ( + "fmt" + "github.com/openziti/fablab/kernel/lib" + "github.com/openziti/fablab/kernel/model" + "github.com/sirupsen/logrus" + "strings" +) + +func Loop3Listener(host *model.Host, joiner chan struct{}, bindAddress string, extraArgs ...string) model.OperatingStage { + return &loopListener{ + host: host, + joiner: joiner, + bindAddress: bindAddress, + subcmd: "loop3", + extraArgs: extraArgs, + } +} + +func LoopListener(host *model.Host, joiner chan struct{}, bindAddress string, extraArgs ...string) model.OperatingStage { + return &loopListener{ + host: host, + joiner: joiner, + bindAddress: bindAddress, + subcmd: "loop2", + extraArgs: extraArgs, + } +} + +func (self *loopListener) Operate(run model.Run) error { + ssh := lib.NewSshConfigFactory(self.host) + if err := lib.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v listener", self.subcmd)); err != nil { + return fmt.Errorf("error killing %v listeners (%w)", self.subcmd, err) + } + + go self.run(run) + return nil +} + +func (self *loopListener) run(run model.Run) { + defer func() { + if self.joiner != nil { + close(self.joiner) + logrus.Debugf("closed joiner") + } + }() + + ssh := lib.NewSshConfigFactory(self.host) + + logFile := fmt.Sprintf("/home/%s/logs/%v-listener-%s.log", ssh.User(), self.subcmd, run.GetId()) + listenerCmd := fmt.Sprintf("/home/%s/fablab/bin/ziti-fabric-test %v listener -b %v %v >> %s 2>&1", + ssh.User(), self.subcmd, self.bindAddress, strings.Join(self.extraArgs, " "), logFile) + if output, err := lib.RemoteExec(ssh, listenerCmd); err != nil { + logrus.Errorf("error starting loop listener [%s] (%v)", output, err) + } +} + +type loopListener struct { + host *model.Host + joiner chan struct{} + bindAddress string + subcmd string + extraArgs []string +} diff --git a/zititest/zitilab/runlevel/5_operation/mesh.go b/zititest/zitilab/runlevel/5_operation/mesh.go new file mode 100644 index 000000000..4e8b30e69 --- /dev/null +++ b/zititest/zitilab/runlevel/5_operation/mesh.go @@ -0,0 +1,158 @@ +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package zitilib_runlevel_5_operation + +import ( + "fmt" + "github.com/openziti/channel/v2" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/identity/dotziti" + "github.com/openziti/transport/v2" + "github.com/sirupsen/logrus" + "time" +) + +func Mesh(closer <-chan struct{}) model.OperatingStage { + return &mesh{closer: closer} +} + +func (mesh *mesh) Operate(run model.Run) error { + if endpoint, id, err := dotziti.LoadIdentity(model.ActiveInstanceId()); err == nil { + if address, err := transport.ParseAddress(endpoint); err == nil { + dialer := channel.NewClassicDialer(id, address, nil) + if ch, err := channel.NewChannel("mesh", dialer, nil, nil); err == nil { + mesh.ch = ch + } else { + return fmt.Errorf("error connecting mesh channel (%w)", err) + } + } else { + return fmt.Errorf("invalid endpoint address (%w)", err) + } + } else { + return fmt.Errorf("unable to load 'fablab' identity (%w)", err) + } + + mesh.m = run.GetModel() + + go mesh.runMesh() + + return nil +} + +func (mesh *mesh) runMesh() { + logrus.Infof("starting") + defer logrus.Infof("exiting") + + for { + select { + case <-time.After(15 * time.Second): + if err := mesh.interrogate(); err != nil { + logrus.Errorf("error querying mesh state (%v)", err) + } + + case <-mesh.closer: + _ = mesh.ch.Close() + return + } + } +} + +// TODO: Update to use REST client +func (mesh *mesh) interrogate() error { + /* + var err error + var body []byte + var listRoutersWaitCh chan *channel.Message + var listLinksWaitCh chan *channel.Message + + listRoutersRequest := &mgmt_pb.ListRoutersRequest{} + body, err = proto.Marshal(listRoutersRequest) + if err != nil { + return fmt.Errorf("error marshaling router list request (%w)", err) + } + requestMsg := channel.NewMessage(int32(mgmt_pb.ContentType_ListRoutersRequestType), body) + listRoutersWaitCh, err = mesh.ch.SendAndWait(requestMsg) + if err != nil { + return fmt.Errorf("error queuing router list request (%w)", err) + } + + listLinksRequest := &mgmt_pb.ListLinksRequest{} + body, err = proto.Marshal(listLinksRequest) + if err != nil { + return fmt.Errorf("error marshaling links list request (%w)", err) + } + requestMsg = channel.NewMessage(int32(mgmt_pb.ContentType_ListLinksRequestType), body) + listLinksWaitCh, err = mesh.ch.SendAndWait(requestMsg) + if err != nil { + return fmt.Errorf("error queuing link list request (%w)", err) + } + + summary := model.ZitiFabricMeshSummary{TimestampMs: info.NowInMilliseconds()} + select { + case listRoutersResponseMsg := <-listRoutersWaitCh: + response := &mgmt_pb.ListRoutersResponse{} + err := proto.Unmarshal(listRoutersResponseMsg.Body, response) + if err != nil { + return fmt.Errorf("error unmarshaling router list response (%w)", err) + } + for _, r := range response.Routers { + if r.Connected { + summary.RouterIds = append(summary.RouterIds, r.Id) + } + } + } + select { + case listLinksResponseMsg := <-listLinksWaitCh: + response := &mgmt_pb.ListLinksResponse{} + err := proto.Unmarshal(listLinksResponseMsg.Body, response) + if err != nil { + return fmt.Errorf("error unmarshaling links list response (%w)", err) + } + for _, l := range response.Links { + summary.Links = append(summary.Links, model.ZitiFabricLinkSummary{ + LinkId: l.Id, + State: l.State, + SrcRouterId: l.Src, + SrcLatency: float64(l.SrcLatency), + DstRouterId: l.Dst, + DstLatency: float64(l.DstLatency), + }) + } + } + + if mesh.m.Data == nil { + mesh.m.Data = make(map[string]interface{}) + } + if _, found := mesh.m.Data["fabric_mesh"]; !found { + mesh.m.Data["fabric_mesh"] = make([]model.ZitiFabricMeshSummary, 0) + } + + summaries := mesh.m.Data["fabric_mesh"].([]model.ZitiFabricMeshSummary) + summaries = append(summaries, summary) + mesh.m.Data["fabric_mesh"] = summaries + + logrus.Infof("