mirror of
https://github.com/openziti/ziti.git
synced 2026-10-15 08:31:50 +00:00
@@ -1,3 +1,12 @@
|
||||
# Release 0.24.2
|
||||
|
||||
## What's New
|
||||
|
||||
* Bug fix: link verification could panic if link was established before control was finished establishing
|
||||
* Bug fix: When checking edge terminator validity in the router, check terminator id as well the address
|
||||
* Enhancement: Improve logging around links in routers. Ensure we close both channels when closing a split link
|
||||
* Enhancement: Add support for inspect in `ziti fabric`. Works the same as `ziti-fabric inspect`
|
||||
|
||||
# Release 0.24.1
|
||||
|
||||
## What's New
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
FROM ubuntu:18.04
|
||||
#
|
||||
# this file mirrors the build params used in the GitHub Actions and enables
|
||||
# reproducible builds for downstream forks and Ziti contributors
|
||||
#
|
||||
|
||||
ARG latest_golang=1.17.2
|
||||
ARG go_distribution_file=go${latest_golang}.linux-amd64.tar.gz
|
||||
ARG GOPATH=/root/go
|
||||
ARG GOROOT=/usr/local/go
|
||||
RUN apt-get update
|
||||
RUN apt-get -yq install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf gcc-aarch64-linux-gnu
|
||||
RUN apt-get -yq install wget build-essential
|
||||
RUN wget -q https://golang.org/dl/${go_distribution_file}
|
||||
RUN tar -xzf ${go_distribution_file} -C /usr/local/
|
||||
RUN mkdir ${GOPATH}
|
||||
ENV GOPATH=${GOPATH}
|
||||
ENV GOROOT=${GOROOT}
|
||||
ENV PATH=$GOPATH/bin:$GOROOT/bin:$PATH
|
||||
RUN go install github.com/mitchellh/gox@latest
|
||||
WORKDIR /mnt
|
||||
CMD ["./linux-build.sh"]
|
||||
|
||||
##
|
||||
# build this Dockerfile
|
||||
##
|
||||
#
|
||||
# MINIMUM_GOLANG=$(grep -Po '^go\s+\K\d+\.\d+(\.\d+)?$' go.mod)
|
||||
# LATEST_GOLANG=$(curl -sSf "https://golang.org/VERSION?m=text" | /bin/grep -Po '^go(\s+)?\K\d+\.\d+\.\d+$')
|
||||
# docker build --tag=zitibuilder --file=Dockerfile.linux-build --build-arg latest_golang=${LATEST_GOLANG} .
|
||||
|
||||
##
|
||||
# build Ziti
|
||||
##
|
||||
# docker run --rm --name=zitibuilder --volume=$PWD:/mnt zitibuilder
|
||||
|
||||
# $ tree ./release
|
||||
# ./release
|
||||
# ├── amd64
|
||||
# │ └── linux
|
||||
# │ ├── ziti
|
||||
# │ ├── ziti-controller
|
||||
# │ ├── ziti-fabric
|
||||
# │ ├── ziti-fabric-gw
|
||||
# │ ├── ziti-fabric-test
|
||||
# │ ├── ziti-probe
|
||||
# │ ├── ziti-router
|
||||
# │ └── ziti-tunnel
|
||||
# ├── arm
|
||||
# │ └── linux
|
||||
# │ ├── ziti
|
||||
# │ ├── ziti-controller
|
||||
# │ ├── ziti-fabric
|
||||
# │ ├── ziti-fabric-gw
|
||||
# │ ├── ziti-fabric-test
|
||||
# │ ├── ziti-probe
|
||||
# │ ├── ziti-router
|
||||
# │ └── ziti-tunnel
|
||||
# └── arm64
|
||||
# └── linux
|
||||
# ├── ziti
|
||||
# ├── ziti-controller
|
||||
# ├── ziti-fabric
|
||||
# ├── ziti-fabric-gw
|
||||
# ├── ziti-fabric-test
|
||||
# ├── ziti-probe
|
||||
# ├── ziti-router
|
||||
# └── ziti-tunnel
|
||||
|
||||
# 6 directories, 24 files
|
||||
@@ -14,11 +14,10 @@ go 1.17
|
||||
|
||||
//replace github.com/michaelquigley/pfxlog => ../pfxlog
|
||||
|
||||
replace go.etcd.io/bbolt => github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e
|
||||
//replace go.etcd.io/bbolt => github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e
|
||||
|
||||
require (
|
||||
github.com/Jeffail/gabs v1.4.0
|
||||
github.com/Jeffail/gabs/v2 v2.6.1
|
||||
github.com/MakeNowJust/heredoc v1.0.0
|
||||
github.com/MichaelMure/go-term-markdown v0.1.4
|
||||
github.com/alecthomas/chroma v0.9.2
|
||||
@@ -34,10 +33,10 @@ require (
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||
github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19
|
||||
github.com/michaelquigley/pfxlog v0.6.3
|
||||
github.com/openziti/edge v0.21.3
|
||||
github.com/openziti/fabric v0.17.2
|
||||
github.com/openziti/foundation v0.16.7
|
||||
github.com/openziti/sdk-golang v0.15.117
|
||||
github.com/openziti/edge v0.21.16
|
||||
github.com/openziti/fabric v0.17.9
|
||||
github.com/openziti/foundation v0.16.9
|
||||
github.com/openziti/sdk-golang v0.15.122
|
||||
github.com/pborman/uuid v1.2.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
@@ -67,7 +66,7 @@ require (
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211106181442-e4c1a74c66bd // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
|
||||
github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/coreos/go-iptables v0.6.0 // indirect
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
|
||||
@@ -123,7 +122,7 @@ require (
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/miekg/pkcs11 v1.0.3 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
|
||||
github.com/netfoundry/secretstream v0.1.2 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
|
||||
@@ -66,7 +66,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
|
||||
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
github.com/Jeffail/gabs/v2 v2.6.1 h1:wwbE6nTQTwIMsMxzi6XFQQYRZ6wDc1mSdxoAN+9U4Gk=
|
||||
github.com/Jeffail/gabs/v2 v2.6.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
@@ -138,8 +137,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
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 v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
@@ -529,7 +528,7 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.2.2/go.mod h1:fa/d1lAdUHxuc1jedx30ZfNG573oQTQmUni3N6pcW+0=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.5.1/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.6.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
|
||||
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/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||
@@ -714,8 +713,8 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||
github.com/mitchellh/mapstructure v1.4.3/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/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@@ -761,19 +760,16 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5+Wa7LQtpGS6/xK7Z+KQXvOAtYgJlA=
|
||||
github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
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.21.3 h1:/cPPmvSHjpCV2S99tukD7YSe4E+MXeHtedFs+0bqOHU=
|
||||
github.com/openziti/edge v0.21.3/go.mod h1:s3U82m//n12qE5rb9Ja3NQY/ZhOTwRxT9kdAahEsGnU=
|
||||
github.com/openziti/fabric v0.17.1/go.mod h1:6AGi2vTZckhZ5W6DfUml8ITUh+UTq1jJabwVNVglcX0=
|
||||
github.com/openziti/fabric v0.17.2 h1:xjZhTx8LGBVKOboaCFbFZwmpOIpi18ODELnNH/IutfQ=
|
||||
github.com/openziti/fabric v0.17.2/go.mod h1:6AGi2vTZckhZ5W6DfUml8ITUh+UTq1jJabwVNVglcX0=
|
||||
github.com/openziti/foundation v0.16.7 h1:Ryuo4wp5CeXJAZYujbXfxuo6/GPpHnvJimESNTopRFY=
|
||||
github.com/openziti/foundation v0.16.7/go.mod h1:DrzmWd4wka7/RlA37KTN2q+dz9dVSH6YJ9VP6xxf28w=
|
||||
github.com/openziti/sdk-golang v0.15.117 h1:XFniHPcc03YLy2ZxRz2E7GhRdiWOonNiMQDA4rjvvig=
|
||||
github.com/openziti/sdk-golang v0.15.117/go.mod h1:ZI3nT0vQ5UgkvK+7P9sGYWajZSMfvq1J4DZUMZYHmPA=
|
||||
github.com/openziti/edge v0.21.16 h1:IRlG6A7nuwu1KcT1LxeQHOPNEp6NPxHKV7Oo5cL5UyE=
|
||||
github.com/openziti/edge v0.21.16/go.mod h1:scsApPeHqL58mza7r5T5AlvLwiZfVN3icygklKIX3fw=
|
||||
github.com/openziti/fabric v0.17.9 h1:s8YmUehZXI6svwNJ01D3VyLr79AT/q470PPqT5q4qBg=
|
||||
github.com/openziti/fabric v0.17.9/go.mod h1:U0oa6oD4alAiJepqPhzGRt5YZgs4aL79Lso/p2ItZqg=
|
||||
github.com/openziti/foundation v0.16.9 h1:iAGPDESXRArGJQYBQSOif+fXfwYRxnvBh68tiXKB1g8=
|
||||
github.com/openziti/foundation v0.16.9/go.mod h1:DrzmWd4wka7/RlA37KTN2q+dz9dVSH6YJ9VP6xxf28w=
|
||||
github.com/openziti/sdk-golang v0.15.122 h1:RxFNpfsXb2wkLlvNpXUoBqABVkt/i8CnhDbk98VM6ig=
|
||||
github.com/openziti/sdk-golang v0.15.122/go.mod h1:FROPdwoM1EkNxcttGtgvOZIJAHhaEe5RqSKF1Zr6aa0=
|
||||
github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231 h1:fa50YL1pzKW+1SsBnJDOHppJN9stOEwS+CRWyUtyYGU=
|
||||
@@ -974,6 +970,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50 h1:ASw9n1EHMftwnP3Az4XW6e308+gNsrHzmdhd0Olz9Hs=
|
||||
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# build the Linux artifacts for amd64, arm, arm64
|
||||
#
|
||||
# see instructions to run reproducible build with Docker in ./Dockerfile.linux-build
|
||||
#
|
||||
set -o pipefail -e -u
|
||||
|
||||
GOX_OUTPUT="release/{{.Arch}}/{{.OS}}/{{.Dir}}"
|
||||
CGO_ENABLED=true gox -os=linux -arch=amd64 -output=${GOX_OUTPUT} ./...
|
||||
CC=arm-linux-gnueabihf-gcc CGO_ENABLED=true gox -cgo -os=linux -arch=arm -output=${GOX_OUTPUT} ./...
|
||||
CC=aarch64-linux-gnu-gcc CGO_ENABLED=true gox -cgo -os=linux -arch=arm64 -output=$GOX_OUTPUT ./...
|
||||
@@ -94,6 +94,21 @@ services:
|
||||
networks:
|
||||
- zitiblue
|
||||
|
||||
ziti-console:
|
||||
image: openziti/zac
|
||||
environment:
|
||||
- ZAC_SERVER_CERT_CHAIN=/openziti/pki/ziti-controller-intermediate/certs/ziti-controller-server.cert
|
||||
- ZAC_SERVER_KEY=/openziti/pki/ziti-controller-intermediate/keys/ziti-controller-server.key -it
|
||||
ports:
|
||||
- "1408:1408"
|
||||
- "8443:8443"
|
||||
volumes:
|
||||
- ziti-fs:/openziti
|
||||
|
||||
networks:
|
||||
- zitiblue
|
||||
- zitired
|
||||
|
||||
networks:
|
||||
zitired:
|
||||
zitiblue:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,21 @@ services:
|
||||
entrypoint: /bin/bash
|
||||
command: "/openziti/scripts/run-edge-router.sh edge"
|
||||
|
||||
ziti-console:
|
||||
image: openziti/zac
|
||||
environment:
|
||||
- ZAC_SERVER_CERT_CHAIN=/openziti/pki/ziti-controller-intermediate/certs/ziti-controller-server.cert
|
||||
- ZAC_SERVER_KEY=/openziti/pki/ziti-controller-intermediate/keys/ziti-controller-server.key -it
|
||||
ports:
|
||||
- "1408:1408"
|
||||
- "8443:8443"
|
||||
volumes:
|
||||
- ziti-fs:/openziti
|
||||
|
||||
networks:
|
||||
- zitiblue
|
||||
- zitired
|
||||
|
||||
networks:
|
||||
zitired:
|
||||
zitiblue:
|
||||
|
||||
@@ -1,323 +0,0 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs/v2"
|
||||
"github.com/openziti/foundation/util/stringz"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ParseContext struct {
|
||||
path string
|
||||
lineNumber int
|
||||
eof bool
|
||||
line string
|
||||
}
|
||||
|
||||
func ScanLines(ctx *ParseContext, callback func(ctx *ParseContext) error) error {
|
||||
file, err := os.Open(ctx.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
ctx.line = line
|
||||
if err := callback(ctx); err != nil {
|
||||
return errors.Wrapf(err, "error parsing %v on line %v", ctx.path, ctx.lineNumber)
|
||||
}
|
||||
ctx.lineNumber++
|
||||
}
|
||||
ctx.eof = true
|
||||
return callback(ctx)
|
||||
}
|
||||
|
||||
type JsonParseContext struct {
|
||||
ParseContext
|
||||
entry *gabs.Container
|
||||
}
|
||||
|
||||
func (self *JsonParseContext) RequiredString(path ...string) (string, error) {
|
||||
v := self.entry.Search(path...)
|
||||
if v == nil || v.Data() == nil {
|
||||
return "", errors.Errorf("%v not found in log entry", strings.Join(path, "."))
|
||||
}
|
||||
s, ok := v.Data().(string)
|
||||
if !ok {
|
||||
return "", errors.Errorf("%v is not a string", strings.Join(path, "."))
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (self *JsonParseContext) ParseJsonEntry() error {
|
||||
input := self.line
|
||||
idx := strings.IndexByte(self.line, '{')
|
||||
if idx < 0 {
|
||||
fmt.Printf("WARN: non-json line: %v", self.line)
|
||||
return nil
|
||||
}
|
||||
if idx > 0 {
|
||||
input = input[idx:]
|
||||
}
|
||||
entry, err := gabs.ParseJSON([]byte(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.entry = entry
|
||||
return nil
|
||||
}
|
||||
|
||||
func ScanJsonLines(ctx *JsonParseContext, callback func(ctx *JsonParseContext) error) error {
|
||||
return ScanLines(&ctx.ParseContext, func(*ParseContext) error {
|
||||
if ctx.eof {
|
||||
return callback(ctx)
|
||||
}
|
||||
if err := ctx.ParseJsonEntry(); err != nil {
|
||||
return err
|
||||
}
|
||||
if ctx.entry != nil {
|
||||
return callback(ctx)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
type LogMatcher interface {
|
||||
Matches(ctx *JsonParseContext) (bool, error)
|
||||
}
|
||||
|
||||
type LogFilter interface {
|
||||
LogMatcher
|
||||
Id() string
|
||||
Label() string
|
||||
Desc() string
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
LogMatcher
|
||||
id string
|
||||
label string
|
||||
desc string
|
||||
}
|
||||
|
||||
func (self *filter) Id() string {
|
||||
return self.id
|
||||
}
|
||||
|
||||
func (self *filter) Label() string {
|
||||
return self.label
|
||||
}
|
||||
|
||||
func (self *filter) Desc() string {
|
||||
return self.desc
|
||||
}
|
||||
|
||||
type JsonLogsParser struct {
|
||||
bucketSize time.Duration
|
||||
currentBucket time.Time
|
||||
filters []LogFilter
|
||||
bucketMatches map[LogFilter]int
|
||||
unmatched int
|
||||
maxUnmatchedLoggedPerBucket int
|
||||
ignore []string
|
||||
}
|
||||
|
||||
func (self *JsonLogsParser) validate() error {
|
||||
ids := map[string]int{}
|
||||
for idx, k := range self.filters {
|
||||
if v, found := ids[k.Id()]; found {
|
||||
return errors.Errorf("duplicate filter id %v at indices %v and %v", k.Id(), idx, v)
|
||||
}
|
||||
ids[k.Id()] = idx
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *JsonLogsParser) ShowCategories(*cobra.Command, []string) {
|
||||
for _, filter := range self.filters {
|
||||
fmt.Printf("%v (%v): %v\n", filter.Id(), filter.Label(), filter.Desc())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *JsonLogsParser) examineLogEntry(ctx *JsonParseContext) error {
|
||||
if ctx.eof {
|
||||
self.dumpBucket()
|
||||
return nil
|
||||
}
|
||||
if err := self.bucket(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, filter := range self.filters {
|
||||
match, err := filter.Matches(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if match {
|
||||
current := self.bucketMatches[filter]
|
||||
self.bucketMatches[filter] = current + 1
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
self.unmatched++
|
||||
if self.unmatched <= self.maxUnmatchedLoggedPerBucket {
|
||||
fmt.Printf("WARN: unmatched line: %v\n\n", ctx.line)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *JsonLogsParser) bucket(ctx *JsonParseContext) error {
|
||||
s, err := ctx.RequiredString("time")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t, err := time.Parse(time.RFC3339, s)
|
||||
if err != nil {
|
||||
return errors.Errorf("time is in an unexpected format: %v", s)
|
||||
}
|
||||
interval := t.Truncate(self.bucketSize)
|
||||
if interval != self.currentBucket {
|
||||
if !self.currentBucket.IsZero() {
|
||||
self.dumpBucket()
|
||||
}
|
||||
self.currentBucket = interval
|
||||
self.bucketMatches = map[LogFilter]int{}
|
||||
self.unmatched = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *JsonLogsParser) dumpBucket() {
|
||||
var filters []LogFilter
|
||||
for k := range self.bucketMatches {
|
||||
if !stringz.Contains(self.ignore, k.Id()) {
|
||||
filters = append(filters, k)
|
||||
}
|
||||
}
|
||||
sort.Slice(filters, func(i, j int) bool {
|
||||
return filters[i].Label() < filters[j].Label()
|
||||
})
|
||||
if len(filters) == 0 && self.unmatched == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v\n---------------------------------------------------\n", self.currentBucket.Format(time.RFC3339))
|
||||
for _, filter := range filters {
|
||||
fmt.Printf(" %v (%v): %0000v\n", filter.Id(), filter.Label(), self.bucketMatches[filter])
|
||||
}
|
||||
if self.unmatched > 0 {
|
||||
fmt.Printf(" unmatched: %0000v\n", self.unmatched)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func FieldStartsWith(field, substring string) LogMatcher {
|
||||
return &EntryFieldStartsWithMatcher{
|
||||
field: field,
|
||||
prefix: substring,
|
||||
}
|
||||
}
|
||||
|
||||
type EntryFieldStartsWithMatcher struct {
|
||||
field string
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (self *EntryFieldStartsWithMatcher) Matches(ctx *JsonParseContext) (bool, error) {
|
||||
fieldValue, err := ctx.RequiredString(self.field)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.HasPrefix(fieldValue, self.prefix), nil
|
||||
}
|
||||
|
||||
func FieldContains(field, substring string) LogMatcher {
|
||||
return &EntryFieldContainsMatcher{
|
||||
field: field,
|
||||
substring: substring,
|
||||
}
|
||||
}
|
||||
|
||||
type EntryFieldContainsMatcher struct {
|
||||
field string
|
||||
substring string
|
||||
}
|
||||
|
||||
func (self *EntryFieldContainsMatcher) Matches(ctx *JsonParseContext) (bool, error) {
|
||||
fieldValue, err := ctx.RequiredString(self.field)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.Contains(fieldValue, self.substring), nil
|
||||
}
|
||||
|
||||
func FieldEquals(field, substring string) LogMatcher {
|
||||
return &EntryFieldContainsMatcher{
|
||||
field: field,
|
||||
substring: substring,
|
||||
}
|
||||
}
|
||||
|
||||
type EntryFieldEqualsMatcher struct {
|
||||
field string
|
||||
value string
|
||||
}
|
||||
|
||||
func (self *EntryFieldEqualsMatcher) Matches(ctx *JsonParseContext) (bool, error) {
|
||||
fieldValue, err := ctx.RequiredString(self.field)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return fieldValue == self.value, nil
|
||||
}
|
||||
|
||||
func AndMatchers(matchers ...LogMatcher) LogMatcher {
|
||||
return &AndMatcher{matchers: matchers}
|
||||
}
|
||||
|
||||
type AndMatcher struct {
|
||||
matchers []LogMatcher
|
||||
}
|
||||
|
||||
func (self *AndMatcher) Matches(ctx *JsonParseContext) (bool, error) {
|
||||
for _, matcher := range self.matchers {
|
||||
result, err := matcher.Matches(ctx)
|
||||
if !result || err != nil {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func FieldMatches(field, expr string) LogMatcher {
|
||||
regex, err := regexp.Compile(expr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &EntryFieldMatchesMatcher{
|
||||
field: field,
|
||||
regex: regex,
|
||||
}
|
||||
}
|
||||
|
||||
type EntryFieldMatchesMatcher struct {
|
||||
field string
|
||||
regex *regexp.Regexp
|
||||
}
|
||||
|
||||
func (self *EntryFieldMatchesMatcher) Matches(ctx *JsonParseContext) (bool, error) {
|
||||
fieldValue, err := ctx.RequiredString(self.field)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return self.regex.MatchString(fieldValue), nil
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewLogsCommand() *cobra.Command {
|
||||
logsCmd := &cobra.Command{
|
||||
Use: "logs",
|
||||
Short: "commands related to analyzing various ziti component logs",
|
||||
}
|
||||
|
||||
parseRouterLogs := &ParseRouterLogs{}
|
||||
parseRouterLogs.Init()
|
||||
|
||||
parseRouterLogsCmd := &cobra.Command{
|
||||
Use: "router",
|
||||
Short: "Parse router logs",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: parseRouterLogs.run,
|
||||
}
|
||||
|
||||
parseRouterLogsCmd.Flags().DurationVarP(&parseRouterLogs.bucketSize, "interval", "n", time.Hour, "Interval for which to aggregate log messages")
|
||||
parseRouterLogsCmd.Flags().IntVarP(&parseRouterLogs.maxUnmatchedLoggedPerBucket, "max-unmatched", "u", 1, "Maximum unmatched log messages to output per bucket")
|
||||
parseRouterLogsCmd.Flags().StringSliceVar(&parseRouterLogs.ignore, "ignore", []string{"IDLE", "CONF"}, "Filters to ignore")
|
||||
|
||||
showRouterLogCategoriesCmd := &cobra.Command{
|
||||
Use: "categories",
|
||||
Short: "Show router log entry categories",
|
||||
Run: parseRouterLogs.ShowCategories,
|
||||
}
|
||||
|
||||
parseRouterLogsCmd.AddCommand(showRouterLogCategoriesCmd)
|
||||
|
||||
logsCmd.AddCommand(parseRouterLogsCmd)
|
||||
|
||||
return logsCmd
|
||||
}
|
||||
|
||||
type ParseRouterLogs struct {
|
||||
JsonLogsParser
|
||||
}
|
||||
|
||||
func (self *ParseRouterLogs) Init() {
|
||||
self.filters = getRouterLogFilters()
|
||||
}
|
||||
|
||||
func getRouterLogFilters() []LogFilter {
|
||||
return []LogFilter{
|
||||
&filter{
|
||||
id: "IDLE",
|
||||
label: "idle circuit scanner",
|
||||
desc: "a circuit has been idle for at least one minute and the controller will be checked to see if the circuit is still valid",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "forwarder/scanner.go"),
|
||||
FieldContains("msg", " idle after "),
|
||||
)},
|
||||
&filter{
|
||||
id: "CONF",
|
||||
label: "circuit confirmation send",
|
||||
desc: "controller has been notified of idle circuits and can respond if they are no longer valid",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("msg", "sent confirmation for "),
|
||||
FieldContains("file", "forwarder/scanner.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "TSCX",
|
||||
label: "tunnel dial success",
|
||||
desc: "a router embedded tunneler has made a successful connection to a server hosting an application",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "successful connection "),
|
||||
FieldContains("file", "xgress_edge_tunnel/dialer.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "DSTX",
|
||||
label: "routing destination exists",
|
||||
desc: "attempting to establish a circuit, but a previous dial attempt already established the egress connection",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "destination exists for "),
|
||||
FieldContains("file", "handler_ctrl/route.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "XGRF",
|
||||
label: "xgress read failure",
|
||||
desc: "read failure on the client or server side of the circuit; will cause the circuit to be torn down",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "read failed"),
|
||||
FieldContains("file", "xgress/xgress.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "XGWF",
|
||||
label: "xgress write failure",
|
||||
desc: "write failure on the client or server side of the circuit; will cause the circuit to be torn down",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "write failed"),
|
||||
FieldContains("file", "xgress/xgress.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "XGBF",
|
||||
label: "xgress can't buffer",
|
||||
desc: "while a circuit was being closed, data was received from the client or server",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "failure to buffer payload"),
|
||||
FieldEquals("error", "payload buffer closed"),
|
||||
FieldContains("file", "xgress/xgress.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCFM",
|
||||
label: "can't forward",
|
||||
desc: "router can't forward a message most likely because the circuit is in the middle of being torn down",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "unable to forward"),
|
||||
FieldContains("file", "handler_xgress/receive.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "CSTO",
|
||||
label: "circuit not started in time",
|
||||
desc: "the terminating side of the circuit didn't receive a start from the initiating side",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "xgress circuit not started in time, closing"),
|
||||
FieldContains("file", "xgress/xgress.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "TLSC",
|
||||
label: "no tls certification provided",
|
||||
desc: "a connection attempt was made to a TLS listener but no certificate was provided",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "error receiving hello from "),
|
||||
FieldContains("msg", "tls: client didn't provide a certificate"),
|
||||
FieldContains("file", "channel2/classic_listener.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LCYT",
|
||||
label: "latency timeout",
|
||||
desc: "a latency ping was sent, but no response was received within the timeout",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "latency timeout after "),
|
||||
FieldContains("file", "metrics/latency.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "CHRX",
|
||||
label: "channel rx error",
|
||||
desc: "channel read failed",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "rx error"),
|
||||
FieldContains("msg", "connection reset by peer"),
|
||||
FieldContains("file", "channel2/impl.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKS",
|
||||
label: "dialing split channel link",
|
||||
desc: "a link is being dialed to another router with separate connections for data and acknowledgements",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "dialing link with split payload/ack channels"),
|
||||
FieldContains("file", "xlink_transport/dialer.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKR",
|
||||
label: "controller requesting dial",
|
||||
desc: "received a request from the controller to dial another router",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "received link connect request"),
|
||||
FieldContains("file", "handler_ctrl/dial.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKD",
|
||||
label: "dialing link",
|
||||
desc: "dialing another router to establish a link",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "dialing link"),
|
||||
FieldContains("file", "handler_ctrl/dial.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKE",
|
||||
label: "link established",
|
||||
desc: "a link to another router has been established",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "link established"),
|
||||
FieldContains("file", "handler_ctrl/dial.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKP",
|
||||
label: "dialing link payload channel",
|
||||
desc: "dialing the link payload channel of a link",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "dialing payload channel for"),
|
||||
FieldContains("file", "xlink_transport/dialer.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKK",
|
||||
label: "dialing link ack channel",
|
||||
desc: "dialing the link ack channel of a link",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "dialing ack channel for"),
|
||||
FieldContains("file", "xlink_transport/dialer.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKC",
|
||||
label: "link closed",
|
||||
desc: "a router to router link was closed",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "link closed"),
|
||||
FieldContains("file", "handler_link/close.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "FLTS",
|
||||
label: "link fault sent",
|
||||
desc: "the router notified the controller that a link failed",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "transmitted link fault"),
|
||||
FieldContains("file", "handler_link/close.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "LNKA",
|
||||
label: "link accepted",
|
||||
desc: "another router has dialed this router and a link has been established",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldStartsWith("msg", "accepted new link"),
|
||||
FieldContains("file", "router/accepter.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCNB",
|
||||
label: "starting reconnect",
|
||||
desc: "the router to controller control channel connection died and the router trying to reconnect",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("msg", "starting reconnection process"),
|
||||
FieldContains("file", "channel2/reconnecting_impl.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCNF",
|
||||
label: "reconnect failed",
|
||||
desc: "the router attempted to reconnect the control channel and failed",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "channel2/reconnecting_dialer.go"),
|
||||
FieldMatches("msg", "reconnection attempt.*failed"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCNS",
|
||||
label: "reconnect succeeded",
|
||||
desc: "the router attempted to reconnect the control channel and succeeded",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "reconnected"),
|
||||
FieldContains("file", "channel2/reconnecting_impl.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCNP",
|
||||
label: "reconnect ping",
|
||||
desc: "the router is checking the control channel to see if it needs to be reconnected",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "channel2/reconnecting_impl.go"),
|
||||
FieldContains("func", "pingInstance"),
|
||||
)},
|
||||
&filter{
|
||||
id: "RCPF",
|
||||
label: "reconnect ping failed",
|
||||
desc: "the router control channel ping failed",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("msg", "unable to ping"),
|
||||
FieldContains("file", "channel2/reconnecting_dialer.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "HELO",
|
||||
label: "received ctrl hello",
|
||||
desc: "the controller sent us a hello message after a control channel was established or reconnected",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("msg", "received server hello"),
|
||||
FieldContains("file", "handler_edge_ctrl/hello.go"),
|
||||
)},
|
||||
&filter{
|
||||
id: "SSST",
|
||||
label: "api session sync started",
|
||||
desc: "The controller has started a full api session sync",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"),
|
||||
FieldMatches("msg", "api session.*starting"),
|
||||
)},
|
||||
&filter{
|
||||
id: "SSCH",
|
||||
label: "api session data received",
|
||||
desc: "The controller sent a chunk of api session data",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"),
|
||||
FieldStartsWith("msg", "received api session sync chunk"),
|
||||
)},
|
||||
&filter{
|
||||
id: "SSDN",
|
||||
label: "api session sync finished",
|
||||
desc: "The controller has finished a full api session sync",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"),
|
||||
FieldStartsWith("msg", "finished sychronizing api sessions"),
|
||||
)},
|
||||
&filter{
|
||||
id: "CHAC",
|
||||
label: "accepted connection",
|
||||
desc: "a tcp connection has been accepted",
|
||||
LogMatcher: AndMatchers(
|
||||
FieldEquals("msg", "accepted connection"),
|
||||
FieldContains("file", "transport/tcp/listener.go"),
|
||||
)},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ParseRouterLogs) run(cmd *cobra.Command, args []string) error {
|
||||
if err := self.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := &JsonParseContext{
|
||||
ParseContext: ParseContext{
|
||||
path: args[0],
|
||||
},
|
||||
}
|
||||
return ScanJsonLines(ctx, self.examineLogEntry)
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
//go:build all
|
||||
|
||||
/*
|
||||
Copyright 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"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/fabric/build"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/openziti/ziti/ziti-ops/logs"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var verbose bool
|
||||
var logFormatter string
|
||||
|
||||
func init() {
|
||||
options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor()
|
||||
pfxlog.GlobalInit(logrus.InfoLevel, options)
|
||||
build.InitBuildInfo(version.GetCmdBuildInfo())
|
||||
|
||||
root.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging")
|
||||
root.PersistentFlags().StringVar(&logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]")
|
||||
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Show component version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(version.GetBuildMetadata(verbose))
|
||||
},
|
||||
})
|
||||
|
||||
root.AddCommand(logs.NewLogsCommand())
|
||||
}
|
||||
|
||||
var root = &cobra.Command{
|
||||
Use: "ziti-ops",
|
||||
Short: "Ziti Ops Tools",
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
if verbose {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
switch logFormatter {
|
||||
case "pfxlog":
|
||||
pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday()))
|
||||
case "json":
|
||||
pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"})
|
||||
case "text":
|
||||
pfxlog.SetFormatter(&logrus.TextFormatter{})
|
||||
default:
|
||||
// let logrus do its own thing
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := root.Execute(); err != nil {
|
||||
fmt.Printf("error: %s\n", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package fabric
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/fabric/rest_client/inspect"
|
||||
"github.com/openziti/fabric/rest_model"
|
||||
"github.com/openziti/foundation/util/stringz"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// newListCmd creates a command object for the "controller list" command
|
||||
func newInspectCmd(p common.OptionsProvider) *cobra.Command {
|
||||
listCmd := &ListCmd{Options: api.Options{CommonOptions: p()}}
|
||||
return listCmd.newCobraCmd()
|
||||
}
|
||||
|
||||
type ListCmd struct {
|
||||
api.Options
|
||||
}
|
||||
|
||||
func (self *ListCmd) newCobraCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "inspect",
|
||||
Short: "Inspect runtime application values",
|
||||
RunE: self.run,
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
}
|
||||
self.AddCommonFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *ListCmd) run(cmd *cobra.Command, args []string) error {
|
||||
client, err := util.NewFabricManagementClient(self)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inspectOk, err := client.Inspect.Inspect(&inspect.InspectParams{
|
||||
Request: &rest_model.InspectRequest{
|
||||
AppRegex: &args[0],
|
||||
RequestedValues: args[1:],
|
||||
},
|
||||
Context: context.Background(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := inspectOk.Payload
|
||||
if *result.Success {
|
||||
fmt.Printf("\nResults: (%d)\n", len(result.Values))
|
||||
for _, value := range result.Values {
|
||||
fmt.Printf("%v.%v\n", stringz.OrEmpty(value.AppID), stringz.OrEmpty(value.Name))
|
||||
fmt.Printf("%v\n\n", stringz.OrEmpty(value.Value))
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("\nEncountered errors: (%d)\n", len(result.Errors))
|
||||
for _, err := range result.Errors {
|
||||
fmt.Printf("\t%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func NewFabricCmd(p common.OptionsProvider) *cobra.Command {
|
||||
|
||||
fabricCmd.AddCommand(newAddIdentityCmd(p), newRemoveIdentityCmd(p))
|
||||
fabricCmd.AddCommand(newCreateCommand(p), newListCmd(p), newUpdateCommand(p), newDeleteCmd(p))
|
||||
|
||||
fabricCmd.AddCommand(newInspectCmd(p))
|
||||
return fabricCmd
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/edge/rest_management_api_client"
|
||||
fabric_rest_client "github.com/openziti/fabric/rest_client"
|
||||
"github.com/openziti/foundation/common/constants"
|
||||
"github.com/openziti/foundation/identity/identity"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
@@ -46,11 +47,13 @@ func (self *RestClientConfig) GetIdentity() string {
|
||||
}
|
||||
|
||||
type RestClientIdentity interface {
|
||||
NewTlsClientConfig() (*tls.Config, error)
|
||||
NewClient(timeout time.Duration, verbose bool) (*resty.Client, error)
|
||||
NewRequest(client *resty.Client) *resty.Request
|
||||
IsReadOnly() bool
|
||||
GetBaseUrlForApi(api API) (string, error)
|
||||
NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error)
|
||||
NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error)
|
||||
NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error)
|
||||
}
|
||||
|
||||
func NewRequest(restClientIdentity RestClientIdentity, timeoutInSeconds int, verbose bool) (*resty.Request, error) {
|
||||
@@ -74,6 +77,21 @@ func (self *RestClientEdgeIdentity) IsReadOnly() bool {
|
||||
return self.ReadOnly
|
||||
}
|
||||
|
||||
func (self *RestClientEdgeIdentity) NewTlsClientConfig() (*tls.Config, error) {
|
||||
rootCaPool := x509.NewCertPool()
|
||||
|
||||
rootPemData, err := ioutil.ReadFile(self.CaCert)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("could not read session certificates [%s]: %v", self.CaCert, err)
|
||||
}
|
||||
|
||||
rootCaPool.AppendCertsFromPEM(rootPemData)
|
||||
|
||||
return &tls.Config{
|
||||
RootCAs: rootCaPool,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *RestClientEdgeIdentity) NewClient(timeout time.Duration, verbose bool) (*resty.Client, error) {
|
||||
client := newClient()
|
||||
client.SetRootCertificate(self.CaCert)
|
||||
@@ -102,85 +120,12 @@ func (self *RestClientEdgeIdentity) GetBaseUrlForApi(api API) (string, error) {
|
||||
return "", errors.Errorf("unsupport api %v", api)
|
||||
}
|
||||
|
||||
func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
respFunc := func(resp *http.Response, err error) {
|
||||
if clientOpts.OutputResponseJson() {
|
||||
if resp == nil || resp.Body == nil {
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), "<empty response body>\n")
|
||||
return
|
||||
}
|
||||
|
||||
resp.Body = ioutil.NopCloser(resp.Body)
|
||||
bodyContent, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not read response body: %v", err)
|
||||
return
|
||||
}
|
||||
bodyStr := string(bodyContent)
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
reqFunc := func(request *http.Request) error {
|
||||
if self.ReadOnly && !strings.EqualFold(request.Method, "get") {
|
||||
return errors.New("this login is marked read-only, only GET operations are allowed")
|
||||
}
|
||||
if clientOpts.OutputRequestJson() {
|
||||
if request == nil || request.Body == nil {
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), "<empty request body>\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
body, err := request.GetBody()
|
||||
if err == nil {
|
||||
_, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not copy request body: %v", err)
|
||||
return nil
|
||||
}
|
||||
bodyContent, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
bodyStr := string(bodyContent)
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
httpClientTransport := &edgeTransport{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 10 * time.Second,
|
||||
}).DialContext,
|
||||
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
ResponseFunc: respFunc,
|
||||
RequestFunc: reqFunc,
|
||||
}
|
||||
|
||||
rootCaPool := x509.NewCertPool()
|
||||
|
||||
rootPemData, err := ioutil.ReadFile(self.CaCert)
|
||||
func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
httpClient, err := newRestClientTransport(clientOpts, self)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("could not read session certificates [%s]: %v", self.CaCert, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootCaPool.AppendCertsFromPEM(rootPemData)
|
||||
|
||||
httpClientTransport.TLSClientConfig = &tls.Config{
|
||||
RootCAs: rootCaPool,
|
||||
}
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: httpClientTransport,
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
parsedHost, err := url.Parse(self.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -195,6 +140,26 @@ func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts EdgeManag
|
||||
return rest_management_api_client.New(clientRuntime, nil), nil
|
||||
}
|
||||
|
||||
func (self *RestClientEdgeIdentity) NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) {
|
||||
httpClient, err := newRestClientTransport(clientOpts, self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parsedHost, err := url.Parse(self.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientRuntime := httptransport.NewWithClient(parsedHost.Host, fabric_rest_client.DefaultBasePath, fabric_rest_client.DefaultSchemes, httpClient)
|
||||
|
||||
clientRuntime.DefaultAuthentication = &EdgeManagementAuth{
|
||||
Token: self.Token,
|
||||
}
|
||||
|
||||
return fabric_rest_client.New(clientRuntime, nil), nil
|
||||
}
|
||||
|
||||
type RestClientFabricIdentity struct {
|
||||
Url string `json:"url"`
|
||||
CaCert string `json:"caCert,omitempty"`
|
||||
@@ -203,6 +168,14 @@ type RestClientFabricIdentity struct {
|
||||
ReadOnly bool `json:"readOnly"`
|
||||
}
|
||||
|
||||
func (self *RestClientFabricIdentity) NewTlsClientConfig() (*tls.Config, error) {
|
||||
id, err := identity.LoadClientIdentity(self.ClientCert, self.ClientKey, self.CaCert)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to load identity")
|
||||
}
|
||||
return id.ClientTLSConfig(), nil
|
||||
}
|
||||
|
||||
func (self *RestClientFabricIdentity) NewClient(timeout time.Duration, verbose bool) (*resty.Client, error) {
|
||||
id, err := identity.LoadClientIdentity(self.ClientCert, self.ClientKey, self.CaCert)
|
||||
if err != nil {
|
||||
@@ -234,10 +207,26 @@ func (self *RestClientFabricIdentity) IsReadOnly() bool {
|
||||
return self.ReadOnly
|
||||
}
|
||||
|
||||
func (self *RestClientFabricIdentity) NewEdgeManagementClient(EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
func (self *RestClientFabricIdentity) NewEdgeManagementClient(ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
return nil, errors.New("fabric identities cannot be used to connect to the edge management API")
|
||||
}
|
||||
|
||||
func (self *RestClientFabricIdentity) NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) {
|
||||
httpClient, err := newRestClientTransport(clientOpts, self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parsedHost, err := url.Parse(self.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientRuntime := httptransport.NewWithClient(parsedHost.Host, fabric_rest_client.DefaultBasePath, fabric_rest_client.DefaultSchemes, httpClient)
|
||||
|
||||
return fabric_rest_client.New(clientRuntime, nil), nil
|
||||
}
|
||||
|
||||
func LoadRestClientConfig() (*RestClientConfig, string, error) {
|
||||
config := &RestClientConfig{}
|
||||
|
||||
@@ -370,3 +359,83 @@ func LoadSelectedRWIdentityForApi(api API) (RestClientIdentity, error) {
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func newRestClientResponseF(clientOpts ClientOpts) func(*http.Response, error) {
|
||||
return func(resp *http.Response, err error) {
|
||||
if clientOpts.OutputResponseJson() {
|
||||
if resp == nil || resp.Body == nil {
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), "<empty response body>\n")
|
||||
return
|
||||
}
|
||||
|
||||
resp.Body = ioutil.NopCloser(resp.Body)
|
||||
bodyContent, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not read response body: %v", err)
|
||||
return
|
||||
}
|
||||
bodyStr := string(bodyContent)
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newRestClientRequestF(clientOpts ClientOpts, readOnly bool) func(*http.Request) error {
|
||||
return func(request *http.Request) error {
|
||||
if readOnly && !strings.EqualFold(request.Method, "get") {
|
||||
return errors.New("this login is marked read-only, only GET operations are allowed")
|
||||
}
|
||||
if clientOpts.OutputRequestJson() {
|
||||
if request == nil || request.Body == nil {
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), "<empty request body>\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
body, err := request.GetBody()
|
||||
if err == nil {
|
||||
_, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not copy request body: %v", err)
|
||||
return nil
|
||||
}
|
||||
bodyContent, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
bodyStr := string(bodyContent)
|
||||
_, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func newRestClientTransport(clientOpts ClientOpts, clientIdentity RestClientIdentity) (*http.Client, error) {
|
||||
httpClientTransport := &edgeTransport{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 10 * time.Second,
|
||||
}).DialContext,
|
||||
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
ResponseFunc: newRestClientResponseF(clientOpts),
|
||||
RequestFunc: newRestClientRequestF(clientOpts, clientIdentity.IsReadOnly()),
|
||||
}
|
||||
|
||||
tlsClientConfig, err := clientIdentity.NewTlsClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpClientTransport.TLSClientConfig = tlsClientConfig
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: httpClientTransport,
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
return httpClient, nil
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/openziti/edge/rest_management_api_client"
|
||||
"github.com/openziti/edge/rest_model"
|
||||
fabric_rest_client "github.com/openziti/fabric/rest_client"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
@@ -766,14 +767,14 @@ func WrapIfApiError(err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
type EdgeManagementClientOpts interface {
|
||||
type ClientOpts interface {
|
||||
OutputRequestJson() bool
|
||||
OutputResponseJson() bool
|
||||
OutputWriter() io.Writer
|
||||
ErrOutputWriter() io.Writer
|
||||
}
|
||||
|
||||
func NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
func NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||
restClientIdentity, err := LoadSelectedIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -781,6 +782,14 @@ func NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_managem
|
||||
return restClientIdentity.NewEdgeManagementClient(clientOpts)
|
||||
}
|
||||
|
||||
func NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) {
|
||||
restClientIdentity, err := LoadSelectedIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return restClientIdentity.NewFabricManagementClient(clientOpts)
|
||||
}
|
||||
|
||||
type EdgeManagementAuth struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user