mirror of
https://github.com/openziti/ziti.git
synced 2026-10-10 06:34:30 +00:00
Implement first service tutorial
This commit is contained in:
@@ -5,6 +5,56 @@
|
||||
* Bug fix: Fabric v0.16.93 fixes `xgress.GetCircuit` to provide a `ctrl not ready` error response when requests arrive before the router is fully online.
|
||||
* Bug fix: Ziti CLI will no longer truncate paths on logins with explicit URLs
|
||||
* Bug fix: Ziti CLI will now correctly check the proper lengths of sha512 hashes in hex format
|
||||
* Feature: Ziti CLI improvements
|
||||
* New interactive tutorial covering creating your first service. Run using: `ziti edge tutorial first-service`
|
||||
* You can now delete multiple entities at once, by providing multiple ids. Ex: `ziti edge delete services one two` or `ziti edge delete service one two` will both work.
|
||||
* You can now delete multiple entities at once, by providing a filter. Ex: `ziti edge delete services where 'name contains "foo"`
|
||||
* Create and delete output now has additional context.
|
||||
* Feature: Terminators can now be filtered by service and router name: Ex: `ziti edge list terminators 'service.name = "echo"'`
|
||||
* Feature: New event type `edge.entityCounts`
|
||||
|
||||
## Entity Count Events
|
||||
The Ziti Controller can now generate events with a summary of how many of each entity type are currently in the data store. It can be configured with an interval for how often the event will be generated. The default interval is five minutes.
|
||||
|
||||
```
|
||||
events:
|
||||
jsonLogger:
|
||||
subscriptions:
|
||||
- type: edge.entityCounts
|
||||
interval: 5m
|
||||
```
|
||||
|
||||
Here is an example of the JSON output of the event:
|
||||
|
||||
```
|
||||
{
|
||||
"namespace": "edge.entityCounts",
|
||||
"timestamp": "2021-08-19T13:39:54.056181406-04:00",
|
||||
"counts": {
|
||||
"apiSessionCertificates": 0,
|
||||
"apiSessions": 9,
|
||||
"authenticators": 4,
|
||||
"cas": 0,
|
||||
"configTypes": 5,
|
||||
"configs": 2,
|
||||
"edgeRouterPolicies": 4,
|
||||
"enrollments": 0,
|
||||
"eventLogs": 0,
|
||||
"geoRegions": 17,
|
||||
"identities": 6,
|
||||
"identityTypes": 4,
|
||||
"mfas": 0,
|
||||
"postureCheckTypes": 5,
|
||||
"postureChecks": 0,
|
||||
"routers": 2,
|
||||
"serviceEdgeRouterPolicies": 2,
|
||||
"servicePolicies": 5,
|
||||
"services": 3,
|
||||
"sessions": 0
|
||||
},
|
||||
"error": ""
|
||||
}
|
||||
```
|
||||
|
||||
# Release 0.22.0
|
||||
|
||||
|
||||
+11
-9
@@ -41,8 +41,8 @@ mgmt:
|
||||
# the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms)
|
||||
#connectTimeoutMs: 3000
|
||||
|
||||
#metrics:
|
||||
#file:
|
||||
#metrics:
|
||||
#file:
|
||||
#path: /tmp/ziti-controller-metrics.log
|
||||
#maxsizemb: 100:wq
|
||||
# Supported formats: json, plain
|
||||
@@ -52,9 +52,9 @@ mgmt:
|
||||
#url: http://localhost:8086
|
||||
#database: ziti
|
||||
|
||||
#events:
|
||||
# jsonLogger:
|
||||
# subscriptions:
|
||||
events:
|
||||
jsonLogger:
|
||||
subscriptions:
|
||||
# - type: fabric.routers
|
||||
# - type: fabric.terminators
|
||||
# - type: metrics
|
||||
@@ -69,10 +69,12 @@ mgmt:
|
||||
# - type: fabric.usage
|
||||
# - type: services
|
||||
# - type: fabric.usage
|
||||
# handler:
|
||||
# type: file
|
||||
# format: json
|
||||
# path: /tmp/ziti-events.log
|
||||
- type: edge.entityCounts
|
||||
interval: 5s
|
||||
handler:
|
||||
type: file
|
||||
format: json
|
||||
path: /tmp/ziti-events.log
|
||||
|
||||
# xctrl_example
|
||||
#
|
||||
|
||||
@@ -19,8 +19,10 @@ replace go.etcd.io/bbolt => github.com/openziti/bbolt v1.3.6-0.20210317142109-54
|
||||
require (
|
||||
github.com/Jeffail/gabs v1.4.0
|
||||
github.com/MakeNowJust/heredoc v1.0.0
|
||||
github.com/MichaelMure/go-term-markdown v0.1.4
|
||||
github.com/alecthomas/chroma v0.9.2
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
|
||||
github.com/go-acme/lego/v4 v4.2.0
|
||||
github.com/go-openapi/runtime v0.19.30
|
||||
@@ -32,13 +34,14 @@ 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.1
|
||||
github.com/openziti/edge v0.20.25
|
||||
github.com/openziti/fabric v0.16.93
|
||||
github.com/openziti/foundation v0.15.69
|
||||
github.com/openziti/sdk-golang v0.15.81
|
||||
github.com/openziti/edge v0.20.29
|
||||
github.com/openziti/fabric v0.16.97
|
||||
github.com/openziti/foundation v0.15.71
|
||||
github.com/openziti/sdk-golang v0.15.85
|
||||
github.com/pborman/uuid v1.2.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/russross/blackfriday v1.5.2
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible
|
||||
@@ -48,6 +51,7 @@ require (
|
||||
github.com/spf13/viper v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/negroni v1.0.0
|
||||
github.com/valyala/fasttemplate v1.2.1
|
||||
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d
|
||||
google.golang.org/grpc v1.38.0
|
||||
|
||||
@@ -45,8 +45,9 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AppsFlyer/go-sundheit v0.4.0 h1:7ECd0YWaXJQ9LzdCFrpGxJVeAgXvNarN6uwxrJsh69A=
|
||||
github.com/AppsFlyer/go-sundheit v0.4.0/go.mod h1:iZ8zWMS7idcvmqewf5mEymWWgoOiG/0WD4+aeh+heX4=
|
||||
github.com/AppsFlyer/go-sundheit v0.5.0 h1:/VxpyigCfJrq1r97mn9HPiAB2qrhcTFHwNIIDr15CZM=
|
||||
github.com/AppsFlyer/go-sundheit v0.5.0/go.mod h1:2ZM0BnfqT/mljBQO224VbL5XH06TgWuQ6Cn+cTtCpTY=
|
||||
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
|
||||
github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=
|
||||
@@ -67,6 +68,10 @@ github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
|
||||
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/MichaelMure/go-term-markdown v0.1.4 h1:Ir3kBXDUtOX7dEv0EaQV8CNPpH+T7AfTh0eniMOtNcs=
|
||||
github.com/MichaelMure/go-term-markdown v0.1.4/go.mod h1:EhcA3+pKYnlUsxYKBJ5Sn1cTQmmBMjeNlpV8nRb+JxA=
|
||||
github.com/MichaelMure/go-term-text v0.3.1 h1:Kw9kZanyZWiCHOYu9v/8pWEgDQ6UVN9/ix2Vd2zzWf0=
|
||||
github.com/MichaelMure/go-term-text v0.3.1/go.mod h1:QgVjAEDUnRMlzpS6ky5CGblux7ebeiLnuy9dAaFZu8o=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
@@ -82,6 +87,17 @@ github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjl
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.18/go.mod h1:L+HB2uBoDgi3+r1pJEJcbGwyyHhd2QXaGsKLbDwtm8Q=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.7.1/go.mod h1:gHw09mkX1Qp80JlYbmN9L3+4R5o6DJJ3GRShh+AICNc=
|
||||
github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs=
|
||||
github.com/alecthomas/chroma v0.9.2/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.458/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
@@ -147,6 +163,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -159,6 +177,11 @@ github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 h1:AqeKSZIG/NIC7
|
||||
github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3/go.mod h1:hEfFauPHz7+NnjR/yHJGhrKo1Za+zStgwUETx3yzqgY=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
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 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
@@ -169,6 +192,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI=
|
||||
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
|
||||
github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 h1:vbix8DDQ/rfatfFr/8cf/sJfIL69i4BcZfjrVOxsMqk=
|
||||
github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75/go.mod h1:0gZuvTO1ikSA5LtTI6E13LEOdWQNjIo5MTQOvrV0eFg=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -179,8 +204,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exoscale/egoscale v0.23.0/go.mod h1:hRo78jkjkCDKpivQdRBEpNYF5+cVpCJCPDg2/r45KaY=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
@@ -383,6 +409,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 h1:Qxs3bNRWe8GTcKMxYOSXm0jx6j0de8XUtb/fsP3GZ0I=
|
||||
github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -546,6 +574,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8/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/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
@@ -556,6 +586,8 @@ github.com/liquidweb/liquidweb-go v1.6.1/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVL
|
||||
github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lucas-clemente/quic-go v0.18.1 h1:DMR7guC0NtVS8zNZR3IO7NARZvZygkSC56GGtC6cyys=
|
||||
github.com/lucas-clemente/quic-go v0.18.1/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucsky/cuid v1.2.1 h1:MtJrL2OFhvYufUIn48d35QGXyeTC8tn0upumW9WwTHg=
|
||||
github.com/lucsky/cuid v1.2.1/go.mod h1:QaaJqckboimOmhRSJXSx/+IT+VTfxfPGSo/6mfgUfmE=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
@@ -582,19 +614,24 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY=
|
||||
@@ -686,14 +723,15 @@ github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5
|
||||
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.20.25 h1:MJxT6HHdKvbM/kxFASOXLkxaFJ0YMO5jt4fBwb0jxq8=
|
||||
github.com/openziti/edge v0.20.25/go.mod h1:Xgc3v/85gWML7XuGMA6TiWCQk/MiHxPyfDhxgJFS7XY=
|
||||
github.com/openziti/fabric v0.16.93 h1:vybizRqfegTj8n9IZG7m2MU1hJUS3mDv8TdAHK/qcOM=
|
||||
github.com/openziti/fabric v0.16.93/go.mod h1:zONdz/0rklchq807hu3j8e6CE+n1zic4spfFblTUrgY=
|
||||
github.com/openziti/foundation v0.15.69 h1:+FuN1RkZUMbUWdAozvyoXKVv5ZYBaVd1e+HUS33YmsE=
|
||||
github.com/openziti/foundation v0.15.69/go.mod h1:Njk4vQbg6ILR/RQiU5DQOk35oMulQRPGHLn386+RSew=
|
||||
github.com/openziti/sdk-golang v0.15.81 h1:ye3zsrzRukWzI4yds2XpMXcx/jv8R6Ocs6lxGvxQWy4=
|
||||
github.com/openziti/sdk-golang v0.15.81/go.mod h1:YuS2GO5sthpny/ycoQB2bXDVET0KNKLLZ/9uGfMH4+k=
|
||||
github.com/openziti/edge v0.20.29 h1:Dsn+q0FvOVdXvoqaGmSC7jtotnS1fNvOAX5yeZ7aOko=
|
||||
github.com/openziti/edge v0.20.29/go.mod h1:VKUk+AjKZ4dLnVXQaquoTrt5Sp2QQf55/wcJGBiS9bE=
|
||||
github.com/openziti/fabric v0.16.96/go.mod h1:unmDyUxL/FKyvSVZdFzkQfVl1gwaeTYV62R7dv2zCxQ=
|
||||
github.com/openziti/fabric v0.16.97 h1:30J85Yxg4ZOlnrTMwZp+gVCoFGKRvIp9WMPR0GUqiU8=
|
||||
github.com/openziti/fabric v0.16.97/go.mod h1:unmDyUxL/FKyvSVZdFzkQfVl1gwaeTYV62R7dv2zCxQ=
|
||||
github.com/openziti/foundation v0.15.71 h1:GOAFIZtthfKhWbuW2W7j4EPXAKDL3oRU9jJVWW9JUzg=
|
||||
github.com/openziti/foundation v0.15.71/go.mod h1:Njk4vQbg6ILR/RQiU5DQOk35oMulQRPGHLn386+RSew=
|
||||
github.com/openziti/sdk-golang v0.15.85 h1:Su7rcN34gcJjWghnovwjiB8KUa5QyTmukJb7H+9G9J0=
|
||||
github.com/openziti/sdk-golang v0.15.85/go.mod h1:EcgYTqC9tr7b5HSiRP+v86tqbR9BjHom1xYfdBctUoc=
|
||||
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=
|
||||
@@ -746,6 +784,9 @@ github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKc
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@@ -759,6 +800,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
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 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
@@ -850,9 +892,11 @@ github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex
|
||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
@@ -909,6 +953,7 @@ go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZ
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -951,6 +996,9 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
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=
|
||||
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 h1:gQ6GUSD102fPgli+Yb4cR/cGaHF7tNBt+GYoRCpGC7s=
|
||||
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -999,6 +1047,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -1074,6 +1123,7 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1115,6 +1165,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/table"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Factory interface {
|
||||
CreateTable(out io.Writer) table.Table
|
||||
}
|
||||
|
||||
type factory struct {
|
||||
Batch bool
|
||||
|
||||
impersonateUser string
|
||||
}
|
||||
|
||||
// NewFactory creates a factory with the default Kubernetes resources defined
|
||||
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
|
||||
// if optionalClientConfig is not nil, then this factory will make use of it.
|
||||
func NewFactory() Factory {
|
||||
return &factory{}
|
||||
}
|
||||
|
||||
func (f *factory) SetBatch(batch bool) {
|
||||
f.Batch = batch
|
||||
}
|
||||
|
||||
// ImpersonateUser returns a new factory impersonating the given user
|
||||
func (f *factory) ImpersonateUser(user string) Factory {
|
||||
copy := *f
|
||||
copy.impersonateUser = user
|
||||
return ©
|
||||
}
|
||||
|
||||
func (f *factory) CreateTable(out io.Writer) table.Table {
|
||||
return table.CreateTable(os.Stdout)
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge_controller"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
@@ -126,11 +126,10 @@ func NewCmdRoot(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Comm
|
||||
initCommands := NewCmdInit(f, out, err)
|
||||
createCommands := NewCmdCreate(f, out, err)
|
||||
updateCommands := NewCmdUpdate(f, out, err)
|
||||
deleteCommands := NewCmdDelete(f, out, err)
|
||||
executeCommands := NewCmdExecute(f, out, err)
|
||||
psCommands := NewCmdPs(f, out, err)
|
||||
pkiCommands := NewCmdPKI(f, out, err)
|
||||
edgeCommand := edge_controller.NewCmdEdge(f, out, err)
|
||||
edgeCommand := edge.NewCmdEdge(f, out, err)
|
||||
logFilter := NewCmdLogFormat(f, out, err)
|
||||
unwrapIdentityFileCommand := NewUnwrapIdentityFileCommand(f, out, err)
|
||||
|
||||
@@ -151,7 +150,6 @@ func NewCmdRoot(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Comm
|
||||
initCommands,
|
||||
createCommands,
|
||||
updateCommands,
|
||||
deleteCommands,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -34,6 +34,17 @@ type Factory interface {
|
||||
CreateTable(out io.Writer) table.Table
|
||||
}
|
||||
|
||||
type OptionsProvider func() CommonOptions
|
||||
|
||||
func NewOptionsProvider(out, err io.Writer) OptionsProvider {
|
||||
return func() CommonOptions {
|
||||
return CommonOptions{
|
||||
Out: out,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CommonOptions contains common options and helper methods
|
||||
type CommonOptions struct {
|
||||
Factory Factory
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
v: 3
|
||||
|
||||
#trace:
|
||||
# path: ctrl.trace
|
||||
|
||||
profile:
|
||||
# cpu:
|
||||
# path: /home/plorenz/tmp/ctrl.cpu.pprof
|
||||
# memory:
|
||||
# path: ctrl.memprof
|
||||
|
||||
db: {{.DatabaseFile}}
|
||||
|
||||
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
|
||||
|
||||
# the endpoint that routers will connect to the controller over.
|
||||
ctrl:
|
||||
listener: tls:{{ .ControlPlane.BindAddress }}:{{ .ControlPlane.Port }}
|
||||
#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
|
||||
|
||||
# the endpoint that management tools connect to the controller over.
|
||||
mgmt:
|
||||
listener: tls:{{ .ManagementPlance.BindAddress }}:{{ .ManagementPlane.Port }}
|
||||
#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:
|
||||
#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: fabric.usage
|
||||
# - type: services
|
||||
# - type: fabric.usage
|
||||
# handler:
|
||||
# type: file
|
||||
# format: json
|
||||
# path: /tmp/ziti-events.log
|
||||
|
||||
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
|
||||
|
||||
{{if .EdgeEnabled }}
|
||||
# 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: 127.0.0.1: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: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/intermediate.cert.pem
|
||||
key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/intermediate.key.decrypted.pem
|
||||
# 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
|
||||
{{end}}
|
||||
|
||||
# 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: {{.Web.BindAddress}}:{{ .Web.Port }}
|
||||
# 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: {{.Web.ExternalAddress}}:{{ .Web.ExternalPort }}
|
||||
# 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
|
||||
{{if .HealthChecksEnabled }}
|
||||
- binding: health-checks
|
||||
options: {}
|
||||
{{end}}
|
||||
{{if .EdgeManagementEnabled }}
|
||||
- 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: {}
|
||||
{{end}}
|
||||
{{if .EdgeClientEnabled}}
|
||||
- binding: edge-client
|
||||
options: {}
|
||||
{{end}}
|
||||
@@ -17,23 +17,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
)
|
||||
|
||||
// CreateOptions contains the command line options
|
||||
type CreateOptions struct {
|
||||
CommonOptions
|
||||
|
||||
DisableImport bool
|
||||
OutDir string
|
||||
}
|
||||
|
||||
var (
|
||||
createLong = templates.LongDesc(`
|
||||
Creates a new Ziti resource.
|
||||
@@ -43,28 +35,16 @@ var (
|
||||
|
||||
// NewCmdCreate creates a command object for the "create" command
|
||||
func NewCmdCreate(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new resource",
|
||||
Long: createLong,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
cmdhelper.CheckErr(cmd.Help())
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdCreateConfig(f, out, errOut))
|
||||
// cmd.AddCommand(NewCmdCreateStateStore(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdCreateConfig(common.NewOptionsProvider(out, errOut)))
|
||||
cmd.AddCommand(NewCmdCreateEnvironment(f, out, errOut))
|
||||
|
||||
cmd.AddCommand(NewCmdPKICreateCA(f, out, errOut))
|
||||
@@ -75,8 +55,3 @@ func NewCmdCreate(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements this command
|
||||
func (o *CreateOptions) Run() error {
|
||||
return o.Cmd.Help()
|
||||
}
|
||||
|
||||
@@ -17,17 +17,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// CreateConfigOptions the options for the create spring command
|
||||
type CreateConfigOptions struct {
|
||||
CreateOptions
|
||||
|
||||
common.CommonOptions
|
||||
Namespace string
|
||||
Version string
|
||||
ReleaseName string
|
||||
@@ -35,15 +32,9 @@ type CreateConfigOptions struct {
|
||||
}
|
||||
|
||||
// NewCmdCreateConfig creates a command object for the "create" command
|
||||
func NewCmdCreateConfig(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func NewCmdCreateConfig(p common.OptionsProvider) *cobra.Command {
|
||||
options := &CreateConfigOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
CommonOptions: p(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@@ -58,10 +49,8 @@ func NewCmdCreateConfig(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cob
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdCreateConfigController(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdCreateConfigRouter(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdCreateConfigMgmt(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdCreateConfigGw(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdCreateConfigController(p))
|
||||
cmd.AddCommand(NewCmdCreateConfigRouter(p))
|
||||
|
||||
options.addFlags(cmd, "", "")
|
||||
return cmd
|
||||
|
||||
@@ -17,14 +17,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
_ "embed"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -46,24 +48,23 @@ var (
|
||||
`)
|
||||
)
|
||||
|
||||
//go:embed config_templates/controller.yml
|
||||
var controllerConfigTemplate string
|
||||
|
||||
// CreateConfigControllerOptions the options for the create spring command
|
||||
type CreateConfigControllerOptions struct {
|
||||
CreateConfigOptions
|
||||
|
||||
OutputFile string
|
||||
DatabaseFile string
|
||||
CtrlListener string
|
||||
}
|
||||
|
||||
// NewCmdCreateConfigController creates a command object for the "create" command
|
||||
func NewCmdCreateConfigController(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func NewCmdCreateConfigController(p common.OptionsProvider) *cobra.Command {
|
||||
options := &CreateConfigControllerOptions{
|
||||
CreateConfigOptions: CreateConfigOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -81,7 +82,6 @@ func NewCmdCreateConfigController(f cmdutil.Factory, out io.Writer, errOut io.Wr
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
options.addFlags(cmd, "", defaultCtrlListener)
|
||||
|
||||
return cmd
|
||||
@@ -93,5 +93,27 @@ func (o *CreateConfigControllerOptions) Run() error {
|
||||
return util.MissingOption(optionCtrlListener)
|
||||
}
|
||||
|
||||
return fmt.Errorf("UNIMPLEMENTED: '%s'", "create config controller")
|
||||
tmpl, err := template.New("controller-config").Parse(controllerConfigTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
baseDir := filepath.Base(o.OutputFile)
|
||||
if baseDir != "." {
|
||||
if err := os.MkdirAll(baseDir, 0700); err != nil {
|
||||
return errors.Wrapf(err, "unable to create directory to house config file: %v", o.OutputFile)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Create(o.OutputFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to create config file: %v", o.OutputFile)
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
if err := tmpl.Execute(f, o); err != nil {
|
||||
return errors.Wrap(err, "unable to execute template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/internal/log"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
)
|
||||
|
||||
const (
|
||||
optionListenAddress = "listenAddress"
|
||||
defaultListenAddress = "localhost:10080"
|
||||
|
||||
optionMgmt = "mgmt"
|
||||
defaultMgmt = "tls:0.0.0.0:10000"
|
||||
|
||||
optionMgmtGwCertPath = "mgmtGwCertPath"
|
||||
|
||||
optionMgmtGwKeyPath = "mgmtGwKeyPath"
|
||||
|
||||
optionMgmtCertPath = "mgmtCertPath"
|
||||
|
||||
optionMgmtKeyPath = "mgmtKeyPath"
|
||||
|
||||
optionMgmtCaCertPath = "mgmtCaCertPath"
|
||||
)
|
||||
|
||||
var (
|
||||
createConfigGwLong = templates.LongDesc(`
|
||||
Creates the gw config
|
||||
`)
|
||||
|
||||
createConfigGwExample = templates.Examples(`
|
||||
# Create the gw config
|
||||
ziti create config gw
|
||||
|
||||
# Create the gw config with a particular ctrlListener
|
||||
ziti create config gw -listenAddress localhost:10080
|
||||
`)
|
||||
)
|
||||
|
||||
// CreateConfigGwOptions the options for the create spring command
|
||||
type CreateConfigGwOptions struct {
|
||||
CreateConfigOptions
|
||||
|
||||
ListenAddress string
|
||||
Mgmt string
|
||||
MgmtGwCertPath string
|
||||
MgmtGwKeyPath string
|
||||
MgmtCertPath string
|
||||
MgmtKeyPath string
|
||||
MgmtCaCertPath string
|
||||
}
|
||||
|
||||
// NewCmdCreateConfigGw creates a command object for the "create" command
|
||||
func NewCmdCreateConfigGw(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &CreateConfigGwOptions{
|
||||
CreateConfigOptions: CreateConfigOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "gw",
|
||||
Short: "Create a gw config",
|
||||
Aliases: []string{"g"},
|
||||
Long: createConfigGwLong,
|
||||
Example: createConfigGwExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
options.addFlags(cmd, "", defaultCtrlListener)
|
||||
|
||||
cmd.Flags().StringVarP(&options.ListenAddress, optionListenAddress, "l", "", "Where the GW should listen for incoming REST requests")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements the command
|
||||
func (o *CreateConfigGwOptions) Run() error {
|
||||
if o.ListenAddress == "" {
|
||||
log.Infof("%s not specified; using default (%s)\n", optionListenAddress, defaultListenAddress)
|
||||
o.ListenAddress = defaultListenAddress
|
||||
// return util.MissingOption(optionListenAddress)
|
||||
}
|
||||
|
||||
gwConfigDir, err := util.ZitiAppConfigDir(c.ZITI_FABRIC_GW)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("err")
|
||||
}
|
||||
|
||||
return fmt.Errorf("UNIMPLEMENTED: '%s'", gwConfigDir)
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
)
|
||||
|
||||
var (
|
||||
createConfigMgmtLong = templates.LongDesc(`
|
||||
Creates the mgmt config
|
||||
`)
|
||||
|
||||
createConfigMgmtExample = templates.Examples(`
|
||||
# Create the mgmt config
|
||||
ziti create config mgmt
|
||||
|
||||
# Create the mgmt config with a particular ctrlListener
|
||||
ziti create config mgmt -ctrlListener quic:0.0.0.0:6262
|
||||
`)
|
||||
)
|
||||
|
||||
// CreateConfigMgmtOptions the options for the create spring command
|
||||
type CreateConfigMgmtOptions struct {
|
||||
CreateConfigOptions
|
||||
|
||||
CtrlAddress string
|
||||
}
|
||||
|
||||
// NewCmdCreateConfigMgmt creates a command object for the "create" command
|
||||
func NewCmdCreateConfigMgmt(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &CreateConfigMgmtOptions{
|
||||
CreateConfigOptions: CreateConfigOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "mgmt",
|
||||
Short: "Create a mgmt config",
|
||||
Aliases: []string{"m"},
|
||||
Long: createConfigMgmtLong,
|
||||
Example: createConfigMgmtExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
options.addFlags(cmd, "", defaultCtrlListener)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements the command
|
||||
func (o *CreateConfigMgmtOptions) Run() error {
|
||||
if o.CtrlAddress == "" {
|
||||
return util.MissingOption(optionCtrlAddress)
|
||||
}
|
||||
|
||||
return fmt.Errorf("UNIMPLEMENTED: '%s'", "create config mgmt")
|
||||
|
||||
// return nil
|
||||
}
|
||||
@@ -18,13 +18,11 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -54,16 +52,10 @@ type CreateConfigRouterOptions struct {
|
||||
}
|
||||
|
||||
// NewCmdCreateConfigRouter creates a command object for the "create" command
|
||||
func NewCmdCreateConfigRouter(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func NewCmdCreateConfigRouter(p common.OptionsProvider) *cobra.Command {
|
||||
options := &CreateConfigRouterOptions{
|
||||
CreateConfigOptions: CreateConfigOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -81,7 +73,6 @@ func NewCmdCreateConfigRouter(f cmdutil.Factory, out io.Writer, errOut io.Writer
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
options.addFlags(cmd, "", defaultCtrlListener)
|
||||
|
||||
return cmd
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
// CreateEnvironmentOptions the options for the create spring command
|
||||
type CreateEnvironmentOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
EnvName string
|
||||
}
|
||||
@@ -36,12 +36,10 @@ type CreateEnvironmentOptions struct {
|
||||
// NewCmdCreateEnvironment creates a command object for the "create" command
|
||||
func NewCmdCreateEnvironment(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &CreateEnvironmentOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -65,12 +63,10 @@ func NewCmdCreateEnvironment(f cmdutil.Factory, out io.Writer, errOut io.Writer)
|
||||
func (o *CreateEnvironmentOptions) addFlags(cmd *cobra.Command, defaultNamespace string, defaultOptionRelease string) {
|
||||
cmd.Flags().StringVarP(&o.EnvName, "name", "", "", "Name of new 'environment'")
|
||||
cmd.MarkFlagRequired("name")
|
||||
|
||||
}
|
||||
|
||||
// Run implements this command
|
||||
func (o *CreateEnvironmentOptions) Run() error {
|
||||
|
||||
deps := make([]string, 0)
|
||||
deps = append(deps, "ansible")
|
||||
err := o.installMissingDependencies(deps)
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"os/user"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
)
|
||||
|
||||
// const (
|
||||
// optionCtrlAddress = "ctrlAddress"
|
||||
// defaultCtrlAddress = "quic:0.0.0.0:6262"
|
||||
// )
|
||||
|
||||
var (
|
||||
createStateStoreLong = templates.LongDesc(`
|
||||
Creates the ziti state-store in S3
|
||||
`)
|
||||
|
||||
createStateStoreExample = templates.Examples(`
|
||||
# Create the ziti state store in S3
|
||||
ziti create state-store
|
||||
|
||||
`)
|
||||
)
|
||||
|
||||
// CreateStateStoreOptions the options for the create spring command
|
||||
type CreateStateStoreOptions struct {
|
||||
CreateOptions
|
||||
}
|
||||
|
||||
// NewCmdCreateStateStore creates a command object for the "create" command
|
||||
func NewCmdCreateStateStore(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &CreateStateStoreOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "state-store",
|
||||
Short: "Create a ziti state-store",
|
||||
Aliases: []string{"ss"},
|
||||
Long: createStateStoreLong,
|
||||
Example: createStateStoreExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements the command
|
||||
func (o *CreateStateStoreOptions) Run() error {
|
||||
|
||||
var defaultBucketName string
|
||||
defaultBucketName = "ziti-state-store"
|
||||
|
||||
bucketName, err := util.PickValue("S3 Bucket Name:", defaultBucketName, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s", err)
|
||||
}
|
||||
|
||||
if bucketName == defaultBucketName {
|
||||
usr, err := user.Current()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s", err)
|
||||
}
|
||||
|
||||
bucketNamePrefix, err := util.PickValue("S3 Bucket Name Prefix (needed because you chose default bucket name):", usr.Username, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s", err)
|
||||
}
|
||||
|
||||
bucketName = bucketNamePrefix + "-" + bucketName
|
||||
}
|
||||
|
||||
err = util.RunAWSCommand("s3api", "create-bucket", "--bucket", bucketName, "--region", "us-east-1")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create state-store bucket '%s'", bucketName)
|
||||
}
|
||||
|
||||
err = util.RunAWSCommand("s3api", "put-bucket-versioning", "--bucket", bucketName, "--versioning-configuration", "Status=Enabled")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to activate versioning on state-store bucket '%s'", bucketName)
|
||||
}
|
||||
|
||||
fmt.Println("\nSuccessfully created S3 bucket '" + bucketName + "'")
|
||||
|
||||
fmt.Println("\nNow, you should create the following environment variable in your current shell and your bash profile:")
|
||||
fmt.Println("\n\tZITI_STATE_STORE=s3://" + bucketName)
|
||||
fmt.Println("")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
)
|
||||
|
||||
// DeleteOptions are the flags for delete commands
|
||||
type DeleteOptions struct {
|
||||
CommonOptions
|
||||
}
|
||||
|
||||
var (
|
||||
deleteLong = templates.LongDesc(`
|
||||
Deletes a resource.
|
||||
`)
|
||||
|
||||
deleteExample = templates.Examples(`
|
||||
# Delete the controller config
|
||||
ziti delete config controller
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdDelete creates a command object for the generic "delete" action
|
||||
func NewCmdDelete(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &DeleteOptions{
|
||||
CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete TYPE [flags]",
|
||||
Short: "Deletes one or many resources",
|
||||
Long: deleteLong,
|
||||
Example: deleteExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{"remove", "rm", "del"},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdDeleteStateStore(f, out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements this command
|
||||
func (o *DeleteOptions) Run() error {
|
||||
return o.Cmd.Help()
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
)
|
||||
|
||||
var (
|
||||
deleteStateStoreLong = templates.LongDesc(`
|
||||
Deletes the ziti state-store from S3
|
||||
`)
|
||||
|
||||
deleteStateStoreExample = templates.Examples(`
|
||||
# Delete the ziti state store from S3
|
||||
ziti delete state-store
|
||||
|
||||
`)
|
||||
)
|
||||
|
||||
// DeleteStateStoreOptions the options for the delete state-store command
|
||||
type DeleteStateStoreOptions struct {
|
||||
DeleteOptions
|
||||
}
|
||||
|
||||
// NewCmdDeleteStateStore creates a command object for the "delete" command
|
||||
func NewCmdDeleteStateStore(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &DeleteStateStoreOptions{
|
||||
DeleteOptions: DeleteOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "state-store",
|
||||
Short: "Delete a ziti state-store",
|
||||
Aliases: []string{"ss"},
|
||||
Long: deleteStateStoreLong,
|
||||
Example: deleteStateStoreExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.addCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements the command
|
||||
func (o *DeleteStateStoreOptions) Run() error {
|
||||
|
||||
var bucketName string
|
||||
|
||||
if bucketName = os.Getenv("ZITI_STATE_STORE"); bucketName == "" {
|
||||
return fmt.Errorf("ZITI_STATE_STORE environment variable is not set")
|
||||
}
|
||||
|
||||
fmt.Println("\nZITI_STATE_STORE environment variable contains '" + bucketName + "'")
|
||||
|
||||
bucketName = strings.Replace(bucketName, "s3://", "", 1)
|
||||
|
||||
message := fmt.Sprintf("Are you sure you want to remove S3 bucket '%s' ?", bucketName)
|
||||
if util.Confirm(message, true, "Please indicate if you would like to remove this S3 bucket.") {
|
||||
|
||||
err := util.RunAWSCommand("s3api", "delete-bucket", "--bucket", bucketName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to delete state-store bucket '%s': '%s'", bucketName, err)
|
||||
}
|
||||
|
||||
fmt.Println("\nSuccessfully removed S3 bucket '" + bucketName + "'")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"io"
|
||||
@@ -33,8 +33,7 @@ func newCreateCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com
|
||||
Short: "creates various entities managed by the Ziti Edge Controller",
|
||||
Long: "Creates various entities managed by the Ziti Edge Controller",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
cmdhelper.CheckErr(cmd.Help())
|
||||
},
|
||||
}
|
||||
|
||||
@@ -48,13 +47,13 @@ func newCreateCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com
|
||||
cmd.AddCommand(newCreateIdentityCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreateServiceCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreateServiceEdgeRouterPolicyCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreateServicePolicyCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreateServicePolicyCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// createEntityOfType create an entity of the given type on the Ziti Edge Controller
|
||||
func createEntityOfType(entityType string, body string, options *edgeOptions) (*gabs.Container, error) {
|
||||
return util.EdgeControllerCreate(entityType, body, options.Out, options.OutputJSONResponse, options.Timeout, options.Verbose)
|
||||
return util.EdgeControllerCreate(entityType, body, options.Out, options.OutputJSONRequest, options.OutputJSONResponse, options.Timeout, options.Verbose)
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"context"
|
||||
+2
-13
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -105,16 +105,5 @@ func runCreateCa(options *createCaOptions) (err error) {
|
||||
setJSONValue(data, options.identityRoles, "identityRoles")
|
||||
|
||||
result, err := createEntityOfType("cas", data.String(), &options.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
id := result.S("data", "id").Data()
|
||||
|
||||
if _, err = fmt.Fprintf(options.Out, "%v\n", id); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return options.logCreateResult("ca", result, err)
|
||||
}
|
||||
+2
-13
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -105,16 +105,5 @@ func runCreateConfig(o *createConfigOptions) error {
|
||||
setJSONValue(entityData, configTypeId, "configTypeId")
|
||||
setJSONValue(entityData, dataMap, "data")
|
||||
result, err := createEntityOfType("configs", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configId := result.S("data", "id").Data()
|
||||
|
||||
if _, err := fmt.Fprintf(o.Out, "%v\n", configId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("config", result, err)
|
||||
}
|
||||
+2
-13
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -102,16 +102,5 @@ func runCreateConfigType(o *createConfigTypeOptions) error {
|
||||
}
|
||||
|
||||
result, err := createEntityOfType("config-types", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configTypeId := result.S("data", "id").Data()
|
||||
|
||||
if _, err := fmt.Fprintf(o.Out, "%v\n", configTypeId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("config type", result, err)
|
||||
}
|
||||
+3
-13
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -82,22 +82,12 @@ func runCreateEdgeRouter(o *createEdgeRouterOptions) error {
|
||||
setJSONValue(entityData, o.appData, "appData")
|
||||
|
||||
result, err := createEntityOfType("edge-routers", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
if err := o.logCreateResult("edge router", result, err); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := result.S("data", "id").Data().(string)
|
||||
|
||||
if !o.OutputJSONResponse {
|
||||
|
||||
//output id
|
||||
if _, err = fmt.Fprintf(o.Out, "%v\n", id); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if o.jwtOutputFile != "" {
|
||||
id := result.S("data", "id").Data().(string)
|
||||
if err := getEdgeRouterJwt(o, id); err != nil {
|
||||
return err
|
||||
}
|
||||
+2
-14
@@ -14,10 +14,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
@@ -87,16 +86,5 @@ func runCreateEdgeRouterPolicy(o *createEdgeRouterPolicyOptions) error {
|
||||
}
|
||||
|
||||
result, err := createEntityOfType("edge-router-policies", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
edgeRouterPolicyId := result.S("data", "id").Data()
|
||||
|
||||
if _, err := fmt.Fprintf(o.Out, "%v\n", edgeRouterPolicyId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("edge router policy", result, err)
|
||||
}
|
||||
+4
-10
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -159,18 +159,12 @@ func runCreateIdentity(idType string, o *createIdentityOptions) error {
|
||||
setJSONValue(entityData, o.servicePrecedences, "serviceHostingPrecedences")
|
||||
|
||||
result, err := createEntityOfType("identities", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
id := result.S("data", "id").Data().(string)
|
||||
|
||||
if _, err = fmt.Fprintf(o.Out, "%v\n", id); err != nil {
|
||||
panic(err)
|
||||
if err := o.logCreateResult("identity", result, err); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.jwtOutputFile != "" {
|
||||
id := result.S("data", "id").Data().(string)
|
||||
if err := getIdentityJwt(o, id, o.edgeOptions.Timeout, o.edgeOptions.Verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
+27
-45
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/openziti/edge/rest_management_api_client/posture_checks"
|
||||
"github.com/openziti/edge/rest_model"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -32,17 +31,17 @@ import (
|
||||
)
|
||||
|
||||
// newCreatePostureCheckCmd creates the 'edge controller create posture-check' command
|
||||
func newCreatePostureCheckCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "posture-check",
|
||||
}
|
||||
|
||||
cmd.AddCommand(newCreatePostureCheckMacCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckDomainCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckProcessCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckOsCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckMfaCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckProcessMultiCmd(f, out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckMacCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckDomainCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckProcessCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckOsCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckMfaCmd(out, errOut))
|
||||
cmd.AddCommand(newCreatePostureCheckProcessMultiCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -106,14 +105,13 @@ func (options *createPostureCheckOptions) addPostureFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new service")
|
||||
}
|
||||
|
||||
func newCreatePostureCheckMacCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckMacCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &createPostureCheckMacOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
@@ -146,14 +144,13 @@ func newCreatePostureCheckMacCmd(f cmdutil.Factory, out io.Writer, errOut io.Wri
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newCreatePostureCheckDomainCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckDomainCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &createPostureCheckDomainOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
@@ -186,14 +183,13 @@ func newCreatePostureCheckDomainCmd(f cmdutil.Factory, out io.Writer, errOut io.
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newCreatePostureCheckProcessCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckProcessCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &createPostureCheckProcessOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
@@ -240,14 +236,13 @@ func newCreatePostureCheckProcessCmd(f cmdutil.Factory, out io.Writer, errOut io
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newCreatePostureCheckProcessMultiCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckProcessMultiCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &createPostureCheckProcessMultiOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
@@ -462,18 +457,7 @@ func runCreatePostureCheckProcess(o *createPostureCheckProcessOptions) error {
|
||||
}
|
||||
|
||||
result, err := createEntityOfType("posture-checks", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
checkId := result.S("data", "id").Data()
|
||||
|
||||
if _, err = fmt.Fprintf(o.Out, "%v\n", checkId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("posture check", result, err)
|
||||
}
|
||||
|
||||
func runCreatePostureCheckProcessMulti(options *createPostureCheckProcessMultiOptions) error {
|
||||
@@ -636,15 +620,14 @@ func runCreatePostureCheckDomain(o *createPostureCheckDomainOptions) (err error)
|
||||
return err
|
||||
}
|
||||
|
||||
func newCreatePostureCheckOsCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckOsCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
|
||||
options := &createPostureCheckOsOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
@@ -742,14 +725,13 @@ func parseOsSpec(osSpecStr string) (*osSpec, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newCreatePostureCheckMfaCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreatePostureCheckMfaCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := createPostureCheckMfaOptions{
|
||||
createPostureCheckOptions: createPostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
tags: make(map[string]string),
|
||||
+2
-14
@@ -14,10 +14,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
@@ -96,16 +95,5 @@ func runCreateService(o *createServiceOptions) (err error) {
|
||||
setJSONValue(entityData, o.tags, "tags")
|
||||
|
||||
result, err := createEntityOfType("services", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceId := result.S("data", "id").Data()
|
||||
|
||||
if _, err = fmt.Fprintf(o.Out, "%v\n", serviceId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("service", result, err)
|
||||
}
|
||||
+2
-14
@@ -14,10 +14,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
@@ -86,16 +85,5 @@ func runCreateServiceEdgeRouterPolicy(o *createServiceEdgeRouterPolicyOptions) e
|
||||
}
|
||||
|
||||
result, err := createEntityOfType("service-edge-router-policies", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
edgeRouterPolicyId := result.S("data", "id").Data()
|
||||
|
||||
if _, err := fmt.Fprintf(o.Out, "%v\n", edgeRouterPolicyId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("service edge router policy", result, err)
|
||||
}
|
||||
+4
-17
@@ -14,10 +14,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
@@ -25,7 +24,6 @@ import (
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -39,10 +37,10 @@ type createServicePolicyOptions struct {
|
||||
}
|
||||
|
||||
// newCreateServicePolicyCmd creates the 'edge controller create service-policy' command
|
||||
func newCreateServicePolicyCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newCreateServicePolicyCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &createServicePolicyOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -104,18 +102,7 @@ func runCreateServicePolicy(o *createServicePolicyOptions) error {
|
||||
setJSONValue(entityData, o.semantic, "semantic")
|
||||
}
|
||||
result, err := createEntityOfType("service-policies", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
servicePolicyId := result.S("data", "id").Data()
|
||||
|
||||
if _, err := fmt.Fprintf(o.Out, "%v\n", servicePolicyId); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return o.logCreateResult("service policy", result, err)
|
||||
}
|
||||
|
||||
func convertNamesToIds(roles []string, entityType string, o edgeOptions) ([]string, error) {
|
||||
+7
-8
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -113,16 +113,15 @@ func runCreateTerminator(o *createTerminatorOptions) (err error) {
|
||||
}
|
||||
|
||||
result, err := createEntityOfType("terminators", entityData.String(), &o.edgeOptions)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
TerminatorId := result.S("data", "id").Data()
|
||||
|
||||
if _, err = fmt.Fprintf(o.Out, "%v\n", TerminatorId); err != nil {
|
||||
panic(err)
|
||||
if !o.OutputJSONResponse {
|
||||
id := result.S("data", "id").Data()
|
||||
_, err = fmt.Fprintf(o.Out, "New %v created with id: %v\n", "terminator", id)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
)
|
||||
|
||||
func newDbCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "db",
|
||||
Short: "Database management operations for the Ziti Edge Controller",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newDbSnapshotCmd(out, errOut))
|
||||
cmd.AddCommand(newDbCheckIntegrityCmd(out, errOut))
|
||||
cmd.AddCommand(newDbCheckIntegrityStatusCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
+5
-6
@@ -1,10 +1,9 @@
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/pkg/errors"
|
||||
@@ -18,10 +17,10 @@ type dbCheckIntegrityOptions struct {
|
||||
fix bool
|
||||
}
|
||||
|
||||
func newDbCheckIntegrityCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newDbCheckIntegrityCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &dbCheckIntegrityOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -62,10 +61,10 @@ func runCheckIntegrityDb(o *dbCheckIntegrityOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func newDbCheckIntegrityStatusCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newDbCheckIntegrityStatusCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &dbCheckIntegrityOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
+3
-4
@@ -14,11 +14,10 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -30,10 +29,10 @@ type dbSnapshotOptions struct {
|
||||
edgeOptions
|
||||
}
|
||||
|
||||
func newDbSnapshotCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newDbSnapshotCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &dbSnapshotOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
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 edge
|
||||
|
||||
import (
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/foundation/storage/boltz"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// newDeleteCmd creates a command object for the "edge controller delete" command
|
||||
func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "deletes various entities managed by the Ziti Edge Controller",
|
||||
Long: "deletes various entities managed by the Ziti Edge Controller",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
newOptions := func() *edgeOptions {
|
||||
return &edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("api-session", newOptions()))
|
||||
cmd.AddCommand(newDeleteAuthenticatorCmd("authenticator", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("ca", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("config", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("config-type", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("edge-router", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("edge-router-policy", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("identity", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service-edge-router-policy", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service-policy", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("session", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("terminator", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("posture-check", newOptions()))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newDeleteCmdForEntityType creates the delete command for the given entity type
|
||||
func newDeleteCmdForEntityType(entityType string, options *edgeOptions) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: entityType + " <id>",
|
||||
Short: "deletes " + getPlural(entityType) + " managed by the Ziti Edge Controller",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Aliases: []string{getPlural(entityType)},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := runDeleteEntityOfType(options, getPlural(entityType))
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
cmd.AddCommand(newDeleteWhereCmdForEntityType(entityType, options))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newDeleteWhereCmdForEntityType(entityType string, options *edgeOptions) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "where <filter>",
|
||||
Short: "deletes " + getPlural(entityType) + " matching the filter managed by the Ziti Edge Controller",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := runDeleteEntityOfTypeWhere(options, getPlural(entityType))
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// runDeleteEntityOfType implements the commands to delete various entity types
|
||||
func runDeleteEntityOfType(o *edgeOptions, entityType string) error {
|
||||
var err error
|
||||
ids := o.Args
|
||||
if entityType != "terminators" && entityType != "api-sessions" && entityType != "sessions" {
|
||||
ids, err = mapNamesToIDs(entityType, *o, ids...)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return deleteEntitiesOfType(o, entityType, ids)
|
||||
}
|
||||
|
||||
func deleteEntitiesOfType(o *edgeOptions, entityType string, ids []string) error {
|
||||
for _, id := range ids {
|
||||
_, err := util.EdgeControllerDelete(entityType, id, o.Out, o.OutputJSONResponse, o.Timeout, o.Verbose)
|
||||
if err != nil {
|
||||
o.Printf("delete of %v with id %v: %v\n", boltz.GetSingularEntityType(entityType), id, color.New(color.FgRed, color.Bold).Sprint("FAIL"))
|
||||
return err
|
||||
}
|
||||
o.Printf("delete of %v with id %v: %v\n", boltz.GetSingularEntityType(entityType), id, color.New(color.FgGreen, color.Bold).Sprint("OK"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// runDeleteEntityOfType implements the commands to delete various entity types
|
||||
func runDeleteEntityOfTypeWhere(options *edgeOptions, entityType string) error {
|
||||
filter := strings.Join(options.Args, " ")
|
||||
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
|
||||
children, pageInfo, err := listEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options.Printf("filter returned ")
|
||||
pageInfo.output(options)
|
||||
|
||||
var ids []string
|
||||
for _, entity := range children {
|
||||
id, _ := entity.Path("id").Data().(string)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
return deleteEntitiesOfType(options, entityType, ids)
|
||||
}
|
||||
|
||||
func getPlural(entityType string) string {
|
||||
if strings.HasSuffix(entityType, "y") {
|
||||
return strings.TrimSuffix(entityType, "y") + "ies"
|
||||
}
|
||||
return entityType + "s"
|
||||
}
|
||||
|
||||
func deleteEntityOfType(entityType string, id string, options *edgeOptions) (*gabs.Container, error) {
|
||||
return util.EdgeControllerDelete(entityType, id, options.Out, options.OutputJSONResponse, options.Timeout, options.Verbose)
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/Jeffail/gabs"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/openziti/edge/rest_model"
|
||||
"github.com/openziti/foundation/util/errorz"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/pkg/errors"
|
||||
@@ -36,7 +35,7 @@ import (
|
||||
)
|
||||
|
||||
// newListCmd creates a command object for the "controller list" command
|
||||
func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newListCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "Lists various entities managed by the Ziti Edge Controller",
|
||||
@@ -49,11 +48,7 @@ func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma
|
||||
|
||||
newOptions := func() *edgeOptions {
|
||||
return &edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +322,12 @@ func listEntitiesWithOptions(entityType string, options *edgeOptions) ([]*gabs.C
|
||||
return listEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
}
|
||||
|
||||
func listEntitiesWithFilter(entityType string, filter string) ([]*gabs.Container, *paging, error) {
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
return listEntitiesOfType(entityType, params, false, nil, 5, false)
|
||||
}
|
||||
|
||||
func filterEntitiesOfType(entityType string, filter string, logJSON bool, out io.Writer, timeout int, verbose bool) ([]*gabs.Container, *paging, error) {
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
@@ -14,14 +14,13 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/pkg/errors"
|
||||
@@ -36,19 +35,20 @@ import (
|
||||
// loginOptions are the flags for login commands
|
||||
type loginOptions struct {
|
||||
edgeOptions
|
||||
Username string
|
||||
Password string
|
||||
Token string
|
||||
Cert string
|
||||
ReadOnly bool
|
||||
Yes bool
|
||||
Username string
|
||||
Password string
|
||||
Token string
|
||||
Cert string
|
||||
ReadOnly bool
|
||||
Yes bool
|
||||
IgnoreConfig bool
|
||||
}
|
||||
|
||||
// newLoginCmd creates the command
|
||||
func newLoginCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newLoginCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &loginOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func newLoginCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comm
|
||||
Use: "login my.controller.hostname[:port]/path",
|
||||
Short: "logs into a Ziti Edge Controller instance",
|
||||
Long: `login allows the ziti command to establish a session with a Ziti Edge Controller, allowing more commands to be run against the controller.`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
@@ -75,6 +75,7 @@ func newLoginCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comm
|
||||
cmd.Flags().StringVarP(&options.Cert, "cert", "c", "", "additional root certificates used by the Ziti Edge Controller")
|
||||
cmd.Flags().BoolVar(&options.ReadOnly, "read-only", false, "marks this login as read-only. Note: this is not a guarantee that nothing can be changed on the server. Care should still be taken!")
|
||||
cmd.Flags().BoolVarP(&options.Yes, "yes", "y", false, "If set, responds to prompts with yes. This will result in untrusted certs being accepted or updated.")
|
||||
cmd.Flags().BoolVar(&options.IgnoreConfig, "ignore-config", false, "If set, does not use value from the config file for hostname or username. Values must be entered or will be prompted for.")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
@@ -82,7 +83,30 @@ func newLoginCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comm
|
||||
|
||||
// Run implements this command
|
||||
func (o *loginOptions) Run() error {
|
||||
host := o.Args[0]
|
||||
config, configFile, err := util.LoadRestClientConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := config.GetIdentity()
|
||||
|
||||
var host string
|
||||
if len(o.Args) == 0 {
|
||||
if defaultId := config.Identities[id]; defaultId != nil && !o.IgnoreConfig {
|
||||
host = defaultId.Url
|
||||
o.Printf("Using controller url: %v from identity '%v' in config file: %v\n", host, id, configFile)
|
||||
} else {
|
||||
if host, err = term.Prompt("Enter controller host[:port] (default localhost:1280): "); err != nil {
|
||||
return err
|
||||
}
|
||||
if host == "" {
|
||||
host = "localhost:1280"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
host = o.Args[0]
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(host, "http") {
|
||||
host = "https://" + host
|
||||
}
|
||||
@@ -115,12 +139,15 @@ func (o *loginOptions) Run() error {
|
||||
|
||||
if o.Token == "" {
|
||||
for o.Username == "" {
|
||||
if o.Username, err = term.Prompt("Enter username: "); err != nil {
|
||||
if defaultId := config.Identities[id]; defaultId != nil && defaultId.Username != "" && !o.IgnoreConfig {
|
||||
o.Username = defaultId.Username
|
||||
o.Printf("Using username: %v from identity '%v' in config file: %v\n", o.Username, id, configFile)
|
||||
} else if o.Username, err = term.Prompt("Enter username: "); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if o.Username != "" && o.Password == "" {
|
||||
if o.Password == "" {
|
||||
if o.Password, err = term.PromptPassword("Enter password: ", false); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -161,18 +188,13 @@ func (o *loginOptions) Run() error {
|
||||
|
||||
loginIdentity := &util.RestClientIdentity{
|
||||
Url: host,
|
||||
Username: o.Username,
|
||||
Token: o.Token,
|
||||
LoginTime: time.Now().Format(time.RFC3339),
|
||||
Cert: o.Cert,
|
||||
ReadOnly: o.ReadOnly,
|
||||
}
|
||||
|
||||
config, configFile, err := util.LoadRestClientConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := config.GetIdentity()
|
||||
o.Printf("Saving identity '%v' to %v\n", id, configFile)
|
||||
config.Identities[id] = loginIdentity
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -31,10 +30,10 @@ type logoutOptions struct {
|
||||
}
|
||||
|
||||
// newLogoutCmd creates the command
|
||||
func newLogoutCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newLogoutCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &logoutOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
+8
-9
@@ -14,13 +14,12 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -28,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
// newPolicyAdvisor creates a command object for the "controller policy-advisor" command
|
||||
func newPolicyAdivsorCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newPolicyAdivsorCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "policy-advisor",
|
||||
Short: "runs sanity checks on various policy related entities managed by the Ziti Edge Controller",
|
||||
@@ -38,8 +37,8 @@ func newPolicyAdivsorCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *co
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newPolicyAdvisorIdentitiesCmd(f, out, errOut))
|
||||
cmd.AddCommand(newPolicyAdvisorServicesCmd(f, out, errOut))
|
||||
cmd.AddCommand(newPolicyAdvisorIdentitiesCmd(out, errOut))
|
||||
cmd.AddCommand(newPolicyAdvisorServicesCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -50,10 +49,10 @@ type policyAdvisorOptions struct {
|
||||
}
|
||||
|
||||
// newPolicyAdvisorIdentitiesCmd creates the 'edge controller policy-advisor identities' command
|
||||
func newPolicyAdvisorIdentitiesCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newPolicyAdvisorIdentitiesCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &policyAdvisorOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -79,10 +78,10 @@ func newPolicyAdvisorIdentitiesCmd(f cmdutil.Factory, out io.Writer, errOut io.W
|
||||
}
|
||||
|
||||
// newPolicyAdvisorServicesCmd creates the 'edge controller policy-advisor services' command
|
||||
func newPolicyAdvisorServicesCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newPolicyAdvisorServicesCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &policyAdvisorOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/ziti/common/enrollment"
|
||||
"io"
|
||||
|
||||
@@ -64,20 +65,35 @@ func (options *edgeOptions) AddCommonFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolVarP(&options.Verbose, "verbose", "", false, "Enable verbose logging")
|
||||
}
|
||||
|
||||
func (options *edgeOptions) logCreateResult(entityType string, result *gabs.Container, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !options.OutputJSONResponse {
|
||||
id := result.S("data", "id").Data()
|
||||
_, err = fmt.Fprintf(options.Out, "New %v %v created with id: %v\n", entityType, options.Args[0], id)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func populateEdgeCommands(f cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Command) *cobra.Command {
|
||||
p := common.NewOptionsProvider(out, errOut)
|
||||
cmd.AddCommand(newCreateCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDeleteCmd(f, out, errOut))
|
||||
cmd.AddCommand(newLoginCmd(f, out, errOut))
|
||||
cmd.AddCommand(newLogoutCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUseCmd(f, out, errOut))
|
||||
cmd.AddCommand(newListCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDeleteCmd(out, errOut))
|
||||
cmd.AddCommand(newLoginCmd(out, errOut))
|
||||
cmd.AddCommand(newLogoutCmd(out, errOut))
|
||||
cmd.AddCommand(newUseCmd(out, errOut))
|
||||
cmd.AddCommand(newListCmd(out, errOut))
|
||||
cmd.AddCommand(newUpdateCmd(f, out, errOut))
|
||||
cmd.AddCommand(newVersionCmd(f, out, errOut))
|
||||
cmd.AddCommand(newPolicyAdivsorCmd(f, out, errOut))
|
||||
cmd.AddCommand(newVerifyCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDbCmd(f, out, errOut))
|
||||
cmd.AddCommand(newVersionCmd(out, errOut))
|
||||
cmd.AddCommand(newPolicyAdivsorCmd(out, errOut))
|
||||
cmd.AddCommand(newVerifyCmd(out, errOut))
|
||||
cmd.AddCommand(newDbCmd(out, errOut))
|
||||
cmd.AddCommand(enrollment.NewEnrollCommand())
|
||||
cmd.AddCommand(newTraceCmd(f, out, errOut))
|
||||
cmd.AddCommand(newTraceCmd(out, errOut))
|
||||
cmd.AddCommand(newTutorialCmd(p))
|
||||
return cmd
|
||||
}
|
||||
|
||||
+5
-6
@@ -14,13 +14,12 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
@@ -34,21 +33,21 @@ type traceIdentityOptions struct {
|
||||
}
|
||||
|
||||
// newCreateIdentityCmd creates the 'edge controller create identity' command
|
||||
func newTraceCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newTraceCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "trace",
|
||||
Short: "manages tracing by the Ziti Edge Controller",
|
||||
}
|
||||
|
||||
cmd.AddCommand(newTraceIdentityCmd(f, out, errOut))
|
||||
cmd.AddCommand(newTraceIdentityCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newTraceIdentityCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newTraceIdentityCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &traceIdentityOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,425 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed tutorials/first-service.md
|
||||
var firstServiceTutorialSource []byte
|
||||
|
||||
//go:embed tutorial_plain_echo_server.go
|
||||
var plainEchoServerSource string
|
||||
|
||||
//go:embed tutorial_plain_echo_client.go
|
||||
var plainEchoClientSource string
|
||||
|
||||
//go:embed tutorial_ziti_echo_client.go
|
||||
var zitiEchoClientSource string
|
||||
|
||||
//go:embed tutorial_ziti_echo_server.go
|
||||
var zitiEchoServerSource string
|
||||
|
||||
func newTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tutorial",
|
||||
Short: "Interactive tutorials for learning about Ziti",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newFirstServiceTutorialCmd(p))
|
||||
cmd.AddCommand(newPlainEchoServerCmd(p))
|
||||
cmd.AddCommand(newPlainEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoServerCmd(p))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type tutorialOptions struct {
|
||||
controllerUrl string
|
||||
username string
|
||||
password string
|
||||
newlinePause time.Duration
|
||||
assumeDefault bool
|
||||
}
|
||||
|
||||
type firstServiceTutorialOptions struct {
|
||||
edgeOptions
|
||||
tutorialOptions
|
||||
}
|
||||
|
||||
func newFirstServiceTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &firstServiceTutorialOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "first-service",
|
||||
Short: "Walks you through creating a service, identity and policies",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.controllerUrl, "controller-url", "", "The Ziti controller URL to use")
|
||||
cmd.Flags().StringVarP(&options.username, "username", "u", "", "The Ziti controller username to use")
|
||||
cmd.Flags().StringVarP(&options.password, "password", "p", "", "The Ziti controller password to use")
|
||||
cmd.Flags().DurationVar(&options.newlinePause, "newline-pause", time.Millisecond*10, "How long to pause between lines when scrolling")
|
||||
cmd.Flags().BoolVar(&options.assumeDefault, "assume-default", false, "Non-interactive mode, assuming default input when user input is required")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *firstServiceTutorialOptions) run() error {
|
||||
t := tutorial.NewRunner()
|
||||
t.NewLinePause = self.newlinePause
|
||||
t.AssumeDefault = self.assumeDefault
|
||||
|
||||
t.RegisterActionHandler("ziti", &ZitiRunnerAction{})
|
||||
t.RegisterActionHandler("ziti-login", &ZitiLoginAction{
|
||||
options: &self.tutorialOptions,
|
||||
})
|
||||
t.RegisterActionHandler("keep-session-alive", &KeepSessionAliveAction{})
|
||||
t.RegisterActionHandler("select-edge-router", &SelectEdgeRouterAction{})
|
||||
|
||||
plainEchoServerActions := &PlainEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-plain-echo-server", plainEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-plain-echo-server", plainEchoServerActions.Stop)
|
||||
|
||||
zitiEchoServerActions := &ZitiEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-ziti-echo-server", zitiEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-ziti-echo-server", zitiEchoServerActions.Stop)
|
||||
|
||||
showActionHandler := tutorial.NewShowActionHandler()
|
||||
showActionHandler.Add("tutorial_plain_echo_server.go", plainEchoServerSource)
|
||||
showActionHandler.Add("tutorial_plain_echo_client.go", plainEchoClientSource)
|
||||
showActionHandler.Add("tutorial_ziti_echo_client.go", zitiEchoClientSource)
|
||||
showActionHandler.Add("tutorial_ziti_echo_server.go", zitiEchoServerSource)
|
||||
t.RegisterActionHandler("show", showActionHandler)
|
||||
|
||||
return t.Run(firstServiceTutorialSource)
|
||||
}
|
||||
|
||||
type ZitiLoginAction struct {
|
||||
options *tutorialOptions
|
||||
}
|
||||
|
||||
func (self *ZitiLoginAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
cmd := "ziti edge login --ignore-config"
|
||||
if self.options.controllerUrl != "" {
|
||||
cmd += " " + self.options.controllerUrl
|
||||
}
|
||||
if self.options.username != "" {
|
||||
cmd += " --username " + self.options.username
|
||||
}
|
||||
if self.options.password != "" {
|
||||
cmd += " --password " + self.options.password
|
||||
}
|
||||
ctx.Body = cmd
|
||||
return (&ZitiRunnerAction{}).Execute(ctx)
|
||||
}
|
||||
|
||||
type ZitiRunnerAction struct{}
|
||||
|
||||
func (self *ZitiRunnerAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
if strings.EqualFold("true", ctx.Headers["templatize"]) {
|
||||
body, err := ctx.Runner.Template(ctx.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Body = body
|
||||
}
|
||||
lines := strings.Split(ctx.Body, "\n")
|
||||
var cmds [][]string
|
||||
buf := &strings.Builder{}
|
||||
buf.WriteString("About to execute:\n\n")
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
params := tutorial.ParseArgumentsWithStrings(line)
|
||||
if params[0] != "ziti" {
|
||||
return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body)
|
||||
}
|
||||
params[0] = line
|
||||
cmds = append(cmds, params)
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(color.New(color.Bold).Sprintf(line))
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
buf.WriteRune('\n')
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString("Continue [Y/N] (default Y): ")
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
tutorial.Continue(buf.String(), true)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
|
||||
colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"])
|
||||
|
||||
allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"])
|
||||
failOk := strings.EqualFold("true", ctx.Headers["failOk"])
|
||||
for _, cmd := range cmds {
|
||||
_, _ = c.Printf("$ %v\n", cmd[0])
|
||||
done := false
|
||||
for !done {
|
||||
if err := tutorial.Exec(os.Args[0], colorStdOut, cmd[1:]...); err != nil {
|
||||
if failOk {
|
||||
return nil
|
||||
}
|
||||
if allowRetry {
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("error while asking about retry: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type KeepSessionAliveAction struct{}
|
||||
|
||||
func (self *KeepSessionAliveAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
interval := time.Minute
|
||||
if val, ok := ctx.Headers["interval"]; ok {
|
||||
if d, err := time.ParseDuration(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
interval = d
|
||||
}
|
||||
}
|
||||
fmt.Printf("Running session refresh every %v\n", interval)
|
||||
go func() {
|
||||
ticker := time.NewTicker(interval)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
_, _, _ = listEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
type edgeRouter struct {
|
||||
id string
|
||||
name string
|
||||
}
|
||||
|
||||
type SelectEdgeRouterAction struct{}
|
||||
|
||||
func (self *SelectEdgeRouterAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
for {
|
||||
err := self.SelectEdgeRouter(ctx)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("Error getting edge router (err=%v). Try again? [Y/N] (default Y): ", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("encountered error prompting for input: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SelectEdgeRouterAction) SelectEdgeRouter(ctx *tutorial.ActionContext) error {
|
||||
fmt.Println("")
|
||||
|
||||
valid := false
|
||||
var edgeRouterName string
|
||||
|
||||
for !valid {
|
||||
children, _, err := listEntitiesWithFilter("edge-routers", "limit none")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to list edge routers")
|
||||
}
|
||||
|
||||
var ers []*edgeRouter
|
||||
|
||||
if len(children) == 0 {
|
||||
return errors.New("no edge routers found")
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
isOnline := child.S("isOnline").Data().(bool)
|
||||
if isOnline {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
ers = append(ers, &edgeRouter{id: id, name: name})
|
||||
}
|
||||
}
|
||||
|
||||
if len(ers) == 0 {
|
||||
fmt.Println("Error: no online edge routers found. Found these offline edge routers: ")
|
||||
for _, child := range children {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
fmt.Printf("id: %10v name: %10v\n", id, name)
|
||||
}
|
||||
return errors.New("no on-line edge routers")
|
||||
}
|
||||
|
||||
fmt.Printf("Available edge routers: \n\n")
|
||||
for idx, er := range ers {
|
||||
fmt.Printf(" %v: %v\n", idx+1, er.name)
|
||||
}
|
||||
fmt.Print(" R: Refresh list from controller\n")
|
||||
var val string
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
val, err = term.Prompt("\nSelect edge router, by number or name (default 1): ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
edgeRouterName = ers[0].name
|
||||
valid = true
|
||||
} else {
|
||||
if idx, err := strconv.Atoi(val); err == nil {
|
||||
if idx > 0 && idx <= len(ers) {
|
||||
edgeRouterName = ers[idx-1].name
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
for _, er := range ers {
|
||||
if val == er.name {
|
||||
edgeRouterName = val
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
if strings.EqualFold("r", val) {
|
||||
fmt.Println("Refreshing edge router list")
|
||||
} else {
|
||||
fmt.Printf("Invalid input %v\n", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Runner.AddVariable("edgeRouterName", edgeRouterName)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PlainEchoServerActions struct {
|
||||
server plainEchoServer
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Runner.AddVariable("port", self.server.Port)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Stop(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Stop plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ZitiEchoServerActions struct {
|
||||
server zitiEchoServer
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
|
||||
self.server.identityJson = "echo-server.json"
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start ziti-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Stop(*tutorial.ActionContext) error {
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
type plainEchoClient struct {
|
||||
host string
|
||||
port uint16
|
||||
}
|
||||
|
||||
func (self *plainEchoClient) echo(input string) error {
|
||||
input = url.QueryEscape(input)
|
||||
u := fmt.Sprintf("http://%v:%v?input=%v", self.host, self.port, input)
|
||||
resp, err := (&http.Client{}).Get(u)
|
||||
if err == nil {
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
c.Print("\nplain-http-echo-client: ")
|
||||
_, err = io.Copy(os.Stdout, resp.Body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// edgeOptions are common options for edge controller commands
|
||||
type plainEchoClientOptions struct {
|
||||
common.CommonOptions
|
||||
port uint16
|
||||
host string
|
||||
}
|
||||
|
||||
func (self *plainEchoClientOptions) run() error {
|
||||
echoClient := &plainEchoClient{
|
||||
host: self.host,
|
||||
port: self.port,
|
||||
}
|
||||
return echoClient.echo(strings.Join(self.Args, " "))
|
||||
}
|
||||
|
||||
func newPlainEchoClientCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &plainEchoClientOptions{
|
||||
CommonOptions: p(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "plain-echo-client strings to echo",
|
||||
Short: "Runs a simple http echo client",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().Uint16Var(&options.port, "port", 80, "Specify the port to dial on")
|
||||
cmd.Flags().StringVar(&options.host, "host", "localhost", "Specify the host to connect to")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type plainEchoServer struct {
|
||||
Port int
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
func (s *plainEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
input := r.URL.Query().Get("input")
|
||||
result := fmt.Sprintf("As you say, '%v', indeed!\n", input)
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
c.Print("\nplain-http-echo-server: ")
|
||||
fmt.Printf("received input '%v'\n", input)
|
||||
if _, err := rw.Write([]byte(result)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *plainEchoServer) run() (err error) {
|
||||
bindAddr := fmt.Sprintf("127.0.0.1:%v", s.Port)
|
||||
s.listener, err = net.Listen("tcp", bindAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr := s.listener.Addr().(*net.TCPAddr)
|
||||
s.Port = addr.Port
|
||||
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
c.Print("\nplain-http-echo-server: ")
|
||||
fmt.Printf("listening on %v\n", addr)
|
||||
go func() { _ = http.Serve(s.listener, http.HandlerFunc(s.ServeHTTP)) }()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *plainEchoServer) stop() error {
|
||||
return s.listener.Close()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
// edgeOptions are common options for edge controller commands
|
||||
type plainEchoServerOptions struct {
|
||||
common.CommonOptions
|
||||
port uint16
|
||||
}
|
||||
|
||||
func (self *plainEchoServerOptions) run() error {
|
||||
echoServer := &plainEchoServer{
|
||||
Port: int(self.port),
|
||||
}
|
||||
if err := echoServer.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(time.Hour * 24 * 365 * 100)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newPlainEchoServerCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &plainEchoServerOptions{
|
||||
CommonOptions: p(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "plain-echo-server",
|
||||
Short: "Runs a simple http echo service",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().Uint16Var(&options.port, "port", 0, "Specify the port to listen on")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NewZitiEchoClient(identityJson string) (*zitiEchoClient, error) {
|
||||
config, err := config.NewFromFile(identityJson)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zitiContext := ziti.NewContextWithConfig(config)
|
||||
|
||||
dial := func(_ context.Context, _ string, addr string) (net.Conn, error) {
|
||||
service := strings.Split(addr, ":")[0] // assume host is service
|
||||
return zitiContext.Dial(service)
|
||||
}
|
||||
|
||||
zitiTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
zitiTransport.DialContext = dial
|
||||
|
||||
return &zitiEchoClient{
|
||||
httpClient: &http.Client{Transport: zitiTransport},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type zitiEchoClient struct {
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func (self *zitiEchoClient) echo(input string) error {
|
||||
u := fmt.Sprintf("http://echo?input=%v", url.QueryEscape(input))
|
||||
resp, err := self.httpClient.Get(u)
|
||||
if err == nil {
|
||||
c := color.New(color.FgGreen, color.Bold)
|
||||
c.Print("\nziti-http-echo-client: ")
|
||||
_, err = io.Copy(os.Stdout, resp.Body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// edgeOptions are common options for edge controller commands
|
||||
type zitiEchoClientOptions struct {
|
||||
common.CommonOptions
|
||||
identity string
|
||||
}
|
||||
|
||||
func (self *zitiEchoClientOptions) run() error {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
echoClient, err := NewZitiEchoClient(self.identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return echoClient.echo(strings.Join(self.Args, " "))
|
||||
}
|
||||
|
||||
func newZitiEchoClientCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &zitiEchoClientOptions{
|
||||
CommonOptions: p(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ziti-echo-client strings to echo",
|
||||
Short: "Runs a ziti-enabled http echo client",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.identity, "identity", "echo-client.json", "Specify the config file to use")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type zitiEchoServer struct {
|
||||
identityJson string
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
func (s *zitiEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
input := r.URL.Query().Get("input")
|
||||
result := fmt.Sprintf("As you say, '%v', indeed!\n", input)
|
||||
c := color.New(color.FgGreen, color.Bold)
|
||||
c.Print("\nziti-http-echo-server: ")
|
||||
fmt.Printf("received input '%v'\n", input)
|
||||
if _, err := rw.Write([]byte(result)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *zitiEchoServer) run() (err error) {
|
||||
config, err := config.NewFromFile(s.identityJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zitiContext := ziti.NewContextWithConfig(config)
|
||||
if s.listener, err = zitiContext.Listen("echo"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := color.New(color.FgGreen, color.Bold)
|
||||
c.Print("\nziti-http-echo-server: ")
|
||||
fmt.Println("listening for connections from echo server")
|
||||
go func() { _ = http.Serve(s.listener, http.HandlerFunc(s.ServeHTTP)) }()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *zitiEchoServer) stop() error {
|
||||
return s.listener.Close()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
// edgeOptions are common options for edge controller commands
|
||||
type zitiEchoServerOptions struct {
|
||||
common.CommonOptions
|
||||
identity string
|
||||
}
|
||||
|
||||
func (self *zitiEchoServerOptions) run() error {
|
||||
echoServer := &zitiEchoServer{
|
||||
identityJson: self.identity,
|
||||
}
|
||||
if err := echoServer.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(time.Hour * 24 * 365 * 100)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newZitiEchoServerCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &zitiEchoServerOptions{
|
||||
CommonOptions: p(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ziti-echo-server",
|
||||
Short: "Runs a ziti-based http echo service",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.identity, "identity", "echo-server.json", "Specify the config file to use")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,474 @@
|
||||
# Introduction
|
||||
|
||||
Hello. In this tutorial we’re going to go explore services, identities and polices.
|
||||
|
||||
Please note: this tutorial can be run interactively, by running 'ziti edge tutorial first-service'. It can also be viewed as a web page [here](https://github.com/openziti/ziti/blob/release-next/ziti/cmd/ziti/cmd/edge/tutorials/first-service.md). It may be convenient to be able to view both at the same time. The interactive version will save you a lot of typing or copy/pasting, but content may be easier to read in a web-browser.
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
## Goals
|
||||
Let’s say you’re the founder of CloudEcho, the number one provider of echo services. When someone needs to hear back what they’ve said, you are here to make that happen. Any way that a customer needs an echo, be it TCP, UDP or HTTP based echo services, you’ve got them covered. You’ve decided to try integrating Ziti into your services and clients. We’re going to look at a few different ways to do that integration and explore different areas of the Ziti model to build an understanding of how to provide and consume services. In this tutorial we’re going look at how to Zitify the HTTP echo service.
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
## Prerequisites
|
||||
|
||||
First, let’s make sure you’ve got an environment running you can work with. We need a Ziti controller and at least one edge router to work with. If you don’t have a controller and edge router running,
|
||||
you can use the quick-start script found [here](https://github.com/openziti/ziti/tree/release-next/quickstart). The fastest way to invoke the quick-start is to run
|
||||
|
||||
`source <(wget -qO- https://raw.githubusercontent.com/openziti/ziti/release-next/quickstart/docker/image/ziti-cli-functions.sh); expressInstall`
|
||||
|
||||
### Authenticate to the controller
|
||||
|
||||
Let's make sure we can connect with the controller. We're going to log in with the Ziti CLI, which will then let us run the rest of our operations.
|
||||
|
||||
```action:ziti-login allowRetry=true
|
||||
ziti edge login
|
||||
```
|
||||
|
||||
Ziti API sessions usually expire after a few minutes. In order to make sure that this session doesn't timeout while the tutorial is running, we're going to run a session keep-alive in the background.
|
||||
|
||||
```action:keep-session-alive interval=1m
|
||||
If your session times out you can run ziti edge login again.
|
||||
```
|
||||
|
||||
### Select Edge Router
|
||||
|
||||
Great, now that we’re logged in, let’s find our local edge router.
|
||||
|
||||
Note that this tutorial assumes that you’ve got an edge router running on the same machine as this tutorial. We'll be using localhost when telling the edge router how to connect to the tutorial services. If you don’t have an edge router running locally, please add one now.
|
||||
|
||||
```action:select-edge-router
|
||||
Pick the name of an edge router to use. It will be referenced in this tutorial as ${edgeRouterName}
|
||||
```
|
||||
|
||||
### Cleanup Tutorial Entities
|
||||
|
||||
Finally, in case you've run this tutorial before or have done other experimentation with this sytem the tutorial may not run cleanly. To ensure a clean run we're going to clean up any entities that would conflict with entities created as part of this tutorial.
|
||||
|
||||
```action:ziti
|
||||
ziti edge delete service echo
|
||||
ziti edge delete identities founder-laptop echo-server
|
||||
ziti edge delete service-policies echo-clients echo-servers
|
||||
ziti edge delete edge-router-policies echo-clients echo-servers
|
||||
ziti edge delete service-edge-router-policy echo
|
||||
```
|
||||
|
||||
# Setting up the Echo Service
|
||||
|
||||
We want to run our echo service over Ziti. We need to create various entities in Ziti for this to work, but the first is the service itself. The most important property of a Ziti service is its name. The service name is similar to a DNS name. When we connect to a service or host a service, we do so by name.
|
||||
|
||||
## Creating the Echo Service
|
||||
|
||||
Let’s create the echo service. The only required property we're providing for now is the name.
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service echo
|
||||
```
|
||||
|
||||
Now that the service has been created, let’s query the service and see what shows up.
|
||||
|
||||
```action:ziti
|
||||
ziti edge list services 'name="echo"'
|
||||
```
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
## Connecting Ziti to our Service
|
||||
|
||||
So, now Ziti has an echo service, but that service doesn’t go anywhere, and we don’t have any way to use it yet. We’re going to start by connecting the service to the applications hosting the service.
|
||||
|
||||
### Plain Echo Service
|
||||
|
||||
Let’s start by assuming we don’t want to make any changes to our server software yet. We’re just going to run an echo server which uses the standard library facilities. Let's start that service now. The source can be found [here](../tutorial_plain_echo_server.go).
|
||||
|
||||
<!---action:show src=tutorial_plain_echo_server.go highlight=go-->
|
||||
|
||||
|
||||
```action:run-plain-echo-server
|
||||
ziti edge tutorial plain-echo-server
|
||||
```
|
||||
|
||||
The output for this service will be prefixed with plain-http-echo-server. The service is running on port ${port}. We can hit this service with a browser at
|
||||
|
||||
```
|
||||
http://localhost:${port}?input=trees%20are%20tall
|
||||
```
|
||||
|
||||
to see the output. Or we can run it with the tutorial plain echo client. The client output will be prefixed with plain-echo-client.
|
||||
|
||||
The source for the plain client code is very simple, and can be found here: [here](../tutorial_plain_echo_client.go)
|
||||
|
||||
<!---action:show src=tutorial_plain_echo_client.go highlight=go-->
|
||||
|
||||
Let's run it and see what the output looks. At this point, we're not sending any traffic over the Ziti network.
|
||||
|
||||
```action:ziti templatize=true colorStdOut=false
|
||||
ziti edge tutorial plain-echo-client --port ${port} trees are tall
|
||||
```
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
### Terminators Overview
|
||||
|
||||
Now that we’ve got the service running, we can tell Ziti how to connect to it. We do that by creating a terminator for the service. A terminator represents an off ramp from the Ziti fabric. When we make a connection through Ziti to a service, the fabric will select a terminator to which traffic will be routed for that connection. For some types of terminators, each connection to the service will result in a new connection from the router to the hosting application. For others, an existing connection between the router and the hosting application will be used.
|
||||
|
||||
### Creating the Terminator
|
||||
|
||||
Let's create the terminator. The arguments to the create terminator command are:
|
||||
|
||||
1. **echo**: The service we’re creating the terminator for
|
||||
1. **${edgeRouterName}**: The edge router we want to use to connect to the application server
|
||||
1. **tcp:localhost:${port}**: The application server address. The format is protocol:hostname-or-ip:port. The protocol can be any of tcp, udp or tls. This address is what the edge router will try to make a
|
||||
connection to when someone uses the service.
|
||||
|
||||
```action:ziti templatize=true
|
||||
ziti edge create terminator echo ${edgeRouterName} tcp:localhost:${port}
|
||||
```
|
||||
|
||||
### Terminator Properties
|
||||
|
||||
Let's take a look at our new terminator:
|
||||
|
||||
```action:ziti failOk=true
|
||||
ziti edge list terminators 'service.name="echo"'
|
||||
```
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
# Client Application
|
||||
|
||||
In order to use the echo service, we need a client application. Our application could embed a Ziti SDK, but unmodified applications can also access Ziti services using a tunneler application. See [Tunnelers](https://openziti.github.io/ziti/clients/tunneler.html) for more information. Even though we're not covering tunnelers here, they are built with the Ziti SDKS. Therefore, all the following setup and configuration applies to them.
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
## SDK Client
|
||||
Let's take a look at our SDK client code (viewable [here](../tutorial_ziti_echo_client.go)). If you compare it with the plain version, you'll notice the actual client code is very similar. The main differences are
|
||||
|
||||
1. We have to load our configuration, so that we can initialize a Ziti Context
|
||||
2. We have to intercept the Dial in the HTTP client, so we can send it through Ziti
|
||||
3. Instead of host:port for the address, we use the service name 'echo'
|
||||
|
||||
<!---action:show src=tutorial_ziti_echo_client.go highlight=go-->
|
||||
|
||||
We can't actually run it yet, because we don't have a configuration for it. As a next step, let's see how we can configure our client, so we can run it.
|
||||
|
||||
<!---action:pause -->
|
||||
|
||||
# Identity Setup
|
||||
|
||||
The main thing our client needs to connect to the Ziti network is an identity. One of the primary functions of Ziti is controlling access to services. In order for us to access the echo service, our client application needs an identity, so that we can permit that identity access.
|
||||
|
||||
## What is an Identity?
|
||||
|
||||
It's tempting to think of an identity as either a user or a device, but neither of those is entirely correct. A user may have multiple devices, each of which accesses the same service. In general a user will have a separate identity for each device from which they access the service. There are a few reasons for this approach:
|
||||
|
||||
* By enrolling each device individually we don’t transfer the credentials between devices. Because we generate the credentials each device, they can’t be intercepted.
|
||||
* If someone compromises one device, we can disable just that identity, rather than everything for a given user.
|
||||
* Traffic becomes attributable to a given device, which can be useful in a number of ways, including identifying misbehaving applications.
|
||||
|
||||
If a user belongs to multiple Ziti networks, they will likely have multiple identities per device. In general, multiple identities on the same device for the same user will not cause any conflicts, unlike trying to run multiple VPNs concurrently. Even when using a Ziti tunnelers, each tunneler can host multiple identities concurrently and there will only be problems if multiple services try to claim the same DNS name or IP.
|
||||
Creating the Identity
|
||||
|
||||
When creating an identity you can specify the identity type as being one of user, service or device. These types are currently just descriptive, and do not affect how Ziti uses the identities. Let’s say you’re running your own software on your laptop. Since you are the company founder, we’ll name the identity founder-laptop. We're also going to assign the identity a role attribute of management. We can use this later when setting up policies.
|
||||
|
||||
```action:ziti
|
||||
ziti edge create identity user founder-laptop -o founder-laptop.jwt --role-attributes management
|
||||
```
|
||||
|
||||
We have now created a new identity of type user with name founder-laptop. When Ziti created the identity, a one-time-token was also generated, which we’ve stored in founder-client.jwt. We’ll use this token to enroll our identity and create the configuration file for our client application.
|
||||
|
||||
Let’s take a look at our new identity:
|
||||
|
||||
```action:ziti
|
||||
ziti edge list identities 'name="founder-laptop"'
|
||||
```
|
||||
|
||||
In addition to the id, name and type we can see that identities, like services and edge routers, also have role-attributes. In the next section we'll be configuring service access, and we’ll see how role attributes come into play.
|
||||
|
||||
Before we can use our new identity, we need to enroll it. Enrolling the identity uses up the one-time-token and generates the configuration, keys and certificates that a client needs to use a Ziti network.
|
||||
|
||||
```action:ziti
|
||||
ziti edge enroll -j founder-laptop.jwt -o founder-laptop.json
|
||||
```
|
||||
|
||||
The resulting json file has the address of the Ziti controller, as well as the keys and certificates it needs to establish its identity and communicate securely with that controller.
|
||||
|
||||
As you saw, the usual flow for enrolling an application in a ziti network has two steps. However, unlike in our approach here, we don’t generally rely on the Ziti CLI to enroll applications and generate a config file. A more conventional flow would be:
|
||||
|
||||
1. Create an identity for the application, which includes generating a JWT
|
||||
1. The application imports JWT, enrolls in the application and stores the configuration in its own format.
|
||||
1. Two ways that applications can import JWTs are by reading a file or reading a QR code
|
||||
|
||||
The reason enrollment is broken into two steps is because we only want the keys and certificates to exist on their final destination. We may transmit the JWT, but once enrollment has completed the JWT cannot be re-used. If someone later steals the JWT, they won’t be able to enroll, as the JWT will no longer be valid. If some intercepts the JWT and uses it to enroll before the intended recipient does, the intended recipient’s enrollment will fail. This lets us know that something is wrong, we can disable the identity, and the intrusion will have been quickly detected.
|
||||
|
||||
<!---action:pause-->
|
||||
|
||||
## Trying the Ziti Client
|
||||
Now that we’re enrolled, let’s try to use our echo service.
|
||||
|
||||
```action:ziti failOk=true
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
Hopefully it comes as no surprise that the echo service wasn’t found, given that we haven’t granted our identity any access yet.
|
||||
|
||||
# Policy Configuration
|
||||
|
||||
The Ziti CLI comes with a tool called policy-advisor to help you figure out if you have correctly configured your policies. Let’s try it out. It can be run either from a service or identity-centric perspective. This following command will check if the founder-laptop identity can access the echo service.
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q founder-laptop echo
|
||||
```
|
||||
|
||||
It should give us three errors.
|
||||
|
||||
1. That the identity has no access to the service
|
||||
1. That the identity has no access to edge routers
|
||||
1. That the service has no access to edge routers
|
||||
|
||||
Let’s tackle these one at a time.
|
||||
|
||||
**Note:** If you don’t see all of those errors, you most likely have other policies affecting your identity or service.
|
||||
|
||||
## Service Policy Setup
|
||||
|
||||
First we need to grant access to use the service via a service policy. There are two types of service policies:
|
||||
|
||||
* Dial - allow using a service
|
||||
* Bind - allow hosting a service
|
||||
|
||||
For now, we just need a dial policy. Later, when we try hosting the echo service with an SDK embedded application, we’ll need a bind policy as well. We're going to explicitly add our service and identity to this policy. The service we'll reference by name. The identity we'll include by role attribute.
|
||||
|
||||
For a deep dive into policies, see [here](https://openziti.github.io/ziti/policies/overview.html).
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service-policy echo-clients Dial --service-roles '@echo' --identity-roles '#management'
|
||||
```
|
||||
|
||||
Let’s check and make sure it’s there:
|
||||
|
||||
```action:ziti
|
||||
ziti edge list service-policies 'name="echo-clients"'
|
||||
```
|
||||
|
||||
If we run the policy-advisor, we should see that we have fixed the first error, and that we have Dial permissions for the echo service.
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q founder-laptop echo
|
||||
```
|
||||
|
||||
If we try to run the client again, it still won’t work, but we should see a different error:
|
||||
|
||||
```action:ziti failOk=true
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
This error indicates that we have access to the service, but not to any edge routers.
|
||||
|
||||
<!---action:pause-->
|
||||
|
||||
# Edge Router Policy Setup
|
||||
|
||||
Now we need to give our client access to one or more edge routers. Edge routers are how client traffic enters a Ziti network. We need to be able to limit which identities can access specific edge routers. Certain edge routers may be dedicated to specific regions, users or services.
|
||||
|
||||
```action:ziti templatize=true
|
||||
ziti edge create edge-router-policy echo-clients --edge-router-roles '@${edgeRouterName}' --identity-roles '#management'
|
||||
```
|
||||
|
||||
Taking a look, we should see now see our new edge router policy in place.
|
||||
|
||||
```action:ziti
|
||||
ziti edge list edge-router-policies 'name="echo-clients"'
|
||||
```
|
||||
|
||||
If we run the policy advisor again, we should see a change.
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q founder-laptop echo
|
||||
```
|
||||
|
||||
We should only have one error left, letting us know that the service doesn’t have any edge routers available to it.
|
||||
|
||||
If we run the client again, we’ll see the same error:
|
||||
|
||||
```action:ziti failOk=true
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
This is because the edge routers that can be used when establishing a session is the set of edge routers that the identity and service have in common.
|
||||
|
||||
Looking at an example:
|
||||
|
||||
1. We have an identity which has access to edge routers A, B, C
|
||||
2. We have a service which can be accessed via edge routers C, D, E
|
||||
3. That identity can only access the service via edge router C, since that's the only one they have in common
|
||||
|
||||
Even though our identity now has access to our edge router, our service does not.
|
||||
|
||||
<!---action:pause-->
|
||||
|
||||
# Service Edge Router Policies
|
||||
In the same way that we can assign edge routers to users, we can also assign them to services. You may wish to do this to conform with local regulations or to give services exclusive access to certain edge routers to meet SLAs.
|
||||
|
||||
Since we don’t have any special requirements right now, let’s let the echo service use all edge routers. There’s a special role attribute of #all which will match all entities of a given type.
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service-edge-router-policy echo --edge-router-roles '#all' --service-roles '@echo'
|
||||
```
|
||||
|
||||
Now if we run the policy advisor again, we should not see any errors.
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q founder-laptop echo
|
||||
```
|
||||
|
||||
We should now finally be able to run the client and get some validation.
|
||||
|
||||
```action:ziti colorStdOut=false
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
We have our first successful connecton through Ziti! **\o/**
|
||||
|
||||
<!---action:pause-->
|
||||
|
||||
# SDK-Embedded Server
|
||||
|
||||
Now that we’ve gotten our end-to-end test working let’s replace our plain server with a Zitified version.
|
||||
|
||||
## Clean up plain server
|
||||
|
||||
Before configuring and running our ziti-embedded server, we're going to stop the plain server and remove any related configurion.
|
||||
|
||||
```action:stop-plain-echo-server
|
||||
Stop the plain echo server
|
||||
```
|
||||
|
||||
We’ve stopped the echo server. If we now run the client, we’ll see an error saying that dialing the service fails.
|
||||
|
||||
```action:ziti colorStdOut=false failOk=true
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
We’re going to also remove the terminator, since that now points to an address where nothing is running.
|
||||
|
||||
```action:ziti
|
||||
ziti edge delete terminators where 'service.name="echo"'
|
||||
```
|
||||
|
||||
If we now run the client, we’ll see an error saying that the service has no terminators.
|
||||
|
||||
```action:ziti colorStdOut=false failOk=true
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
## Hosting Identity
|
||||
|
||||
Since we’re going to use the SDK in the server, we need an identity for the server.
|
||||
|
||||
```action:ziti
|
||||
ziti edge create identity service echo-server -o echo-server.jwt --role-attributes echo-server
|
||||
```
|
||||
|
||||
We’ll then enroll the server identity.
|
||||
|
||||
```action:ziti
|
||||
ziti edge enroll -j echo-server.jwt -o echo-server.json
|
||||
```
|
||||
|
||||
## Ziti Server Code
|
||||
|
||||
If you look at the server code, viewable [here](../tutorial_ziti_echo_server.go), you should notice very few changes from the plain echo server. The actual request processing code is unchanged.
|
||||
|
||||
<!---action:show src=tutorial_ziti_echo_server.go highlight=go-->
|
||||
|
||||
Let’s try running it and see what happens.
|
||||
|
||||
```action:ziti colorStdOut=false failOk=true
|
||||
ziti edge tutorial ziti-echo-server --identity echo-server.json
|
||||
```
|
||||
|
||||
Since we haven’t given this identity access to the server, it fails.
|
||||
|
||||
## Server Side Policy Configuration
|
||||
|
||||
Let’s run the policy advisor first and see what it has to say.
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q echo-server echo
|
||||
```
|
||||
|
||||
We should only see two errors.
|
||||
|
||||
* The identity does not have access to the service
|
||||
* The identity does not have access to any edge routers
|
||||
|
||||
We already granted the echo service to all edge routers, so that is no longer an issue.
|
||||
|
||||
First, let’s grant the identity access to the service. Unlike before, we’re not granting access to use the service, but to host it. So instead of a Dial policy, we need to create a Bind policy.
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service-policy echo-servers Bind --service-roles '@echo' --identity-roles '#echo-server'
|
||||
```
|
||||
|
||||
We now have two service policies, one for clients and one for hosts
|
||||
|
||||
```action:ziti
|
||||
ziti edge list service-policies 'name contains "echo"'
|
||||
```
|
||||
|
||||
Running the policy advisor again, we should be down to one error:
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q echo-server echo
|
||||
```
|
||||
|
||||
Finally, we create an edge router policy for the hosting identity. In this case, it has the same servers as the client side, but generally client side and hosting side identities will use different sets of edge routers.
|
||||
|
||||
```action:ziti templatize=true
|
||||
ziti edge create edge-router-policy echo-servers --edge-router-roles '@${edgeRouterName}' --identity-roles '#echo-server'
|
||||
```
|
||||
|
||||
We should now get a clean bill of health from the policy advisor
|
||||
|
||||
```action:ziti
|
||||
ziti edge policy-advisor identities -q echo-server echo
|
||||
```
|
||||
|
||||
Let’s give it a try now and see what happens:
|
||||
|
||||
```action:run-ziti-echo-server
|
||||
ziti edge tutorial ziti-echo-server
|
||||
```
|
||||
|
||||
Our client should work correctly. Hang on, you may be saying… won’t it fail with a ‘no terminators’ error? After all, we haven’t created a new terminator yet. Well, let’s take a look at our terminators:
|
||||
|
||||
```action:ziti failOk=true
|
||||
ziti edge list terminators 'service.name="echo"'
|
||||
```
|
||||
|
||||
There’s a terminator present, which looks quite different from the one we created manually. This terminator was created dynamically when the ziti-echo-server application bound the service. Client connections for echo will now get made over the existing network connection that the server application has with the edge router. When you stop the server application, the terminator will be removed.
|
||||
|
||||
This has some interesting benefits. For example, this can make horizontal scale easier to accomplish. When you spin up new instances of the server application, they can connect, dynamically create a terminator and start receiving a portion of the service traffic. When you stop an application, or it dies, the connection goes away, and the terminator is automatically removed. New connections won’t try to connect that application server anymore.
|
||||
|
||||
Hosting configuration and topologies is a big topic. For now, let’s try out our client with our single server instance running:
|
||||
|
||||
```action:ziti colorStdOut=false
|
||||
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
|
||||
```
|
||||
|
||||
Success, we now have a Ziti SDK-embedded client, communicating with a Ziti SDK-embedded server.
|
||||
|
||||
Thanks for taking the time to learn about Ziti services, identities and policies!
|
||||
|
||||
Hopefully you’ve gotten a better idea of:
|
||||
|
||||
* How to create and manage services and identities
|
||||
* How terminators connect the Ziti fabric with application servers
|
||||
* How to manage client access with identities and service policies
|
||||
* How edge routers can be assigned across identities with edge router policies
|
||||
* How edge routers can be assigned across services with service edge router polices
|
||||
|
||||
|
||||
See the [Documentation Hub](https://openziti.github.io/) for more resources.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Introduction
|
||||
This document contains more in-depth information for various Ziti topics. Most of this should be folded into the docs, but it's here as a resource for now.
|
||||
|
||||
## Edge Router Topologies
|
||||
When developing or testing we may send all traffic through a single router. This is not how a Ziti network would commonly be deployed. Usually there would be multiple routers co-located with the application servers, hosted so that they were not reachable from the public internet. These routers would reach out to routers hosted on the public internet. Clients would connect to the public facing routers.
|
||||
|
||||
## Service Properties
|
||||
|
||||
Let’s take a look at each of the service properties:
|
||||
|
||||
### id
|
||||
|
||||
A system generated immutable ID. Different UIs like the CLI and the admin console will generally allow you to reference things by name. The ID just provides a stable unique ID, as opposed to the name, which must also be unique but can change.
|
||||
|
||||
### name
|
||||
|
||||
A user provided unique, mutable identifier. Generally used for display.
|
||||
|
||||
### encryption required
|
||||
|
||||
Ziti encrypts communications between processes when configured with TLS. This means data will be encrypted on the wire between the client and routers and in the context of router to router communication. Routers must decrypt data in memory in order to perform routing. This can be avoided, as Ziti SDKs also provide for transparent end-to-end encryption. This means that Ziti SDKs will encrypt your data before it enters a Ziti network, and it won't be decrypted until it is received on the other side. This flag controls whether this encryption is mandatory. If you set the flag on a service and end-to-end encryption handshaking fails, the SDKs will fail the connection rather than falling back to unencrypted communication.
|
||||
|
||||
### terminator strategy
|
||||
|
||||
This comes into play when you have multiple ways to route traffic to the application(s) hosting the service. This could be:
|
||||
|
||||
* Multiple application servers, either for a HA (high availability) or horizontal scaling
|
||||
* Multiple routers configured to go to a single application server, for redundancy or performance of the Ziti network
|
||||
* A combination of the two
|
||||
|
||||
The strategy determines how we pick which application gets a particular connection attempt via which route.
|
||||
See [Ziti Services | Terminators](https://openziti.github.io/ziti/services/overview.html?tabs=create-service-ui#terminators) for more information.
|
||||
|
||||
### role attributes
|
||||
|
||||
Used by the policy system. We’ll cover this in more details shortly.
|
||||
|
||||
# Terminator
|
||||
Taking a look at the results, the id, service, router and address properties should all make sense. Let’s take a brief look at some properties.
|
||||
|
||||
#### binding
|
||||
|
||||
Different terminators can be handled by different code in the routers. This tells the router how this terminator should be treated. An edge_transport binding directs the router to use a module which knows how to handle edge end-to-end encryption and connect to TCP and TLS addresses. We’ll see a different type of binding when we look at app-embedded hosting.
|
||||
|
||||
#### identity
|
||||
|
||||
Used by P2P or mesh type services, for example VoIP. Generally used when you have multiple applications all hosting the same service, and you need to be able to reach a specific one. For example, you may have many VoIP applications all hosting a VoIP service. When you dial the service, you'll want to connect to the specific application that the person you're trying to reach is running.
|
||||
|
||||
#### cost, precedence and dynamic-cost
|
||||
|
||||
These properties are all used by terminator strategies. We’ll cover them in the hosting tutorial.
|
||||
|
||||
Now that we have configured the service side of our service, let’s take a look at the client side.
|
||||
|
||||
# Tunnelers
|
||||
|
||||
If we have an existing client application which doesn’t have Ziti embedded, the Ziti project provides some applications which can bridge the gap between a plain client application and a Ziti-hosted service. They generally work by acting as a proxy, intercepting network traffic and redirecting it through Ziti. They can even intercept DNS names and IP addresses, so that client configuration doesn’t need to change. We're not going to demonstrate a tunneler as part of this tutorial, but know that there are options available for those cases where embedding an SDK into the application isn’t feasible, or you need an intermediary solution.
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/Jeffail/gabs"
|
||||
@@ -49,7 +49,7 @@ func newUpdateCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com
|
||||
cmd.AddCommand(newUpdateServicePolicyCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdateServiceEdgeRouterPolicyCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdateTerminatorCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+17
-18
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -25,21 +25,20 @@ import (
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// newUpdatePostureCheckCmd creates the 'edge controller update posture-check' command
|
||||
func newUpdatePostureCheckCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "posture-check",
|
||||
}
|
||||
|
||||
cmd.AddCommand(newUpdatePostureCheckMacCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckDomainCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckProcessCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckOsCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckMfaCmd(f, out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckMacCmd(out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckDomainCmd(out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckProcessCmd(out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckOsCmd(out, errOut))
|
||||
cmd.AddCommand(newUpdatePostureCheckMfaCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -82,11 +81,11 @@ type updatePostureCheckOsOptions struct {
|
||||
os []string
|
||||
}
|
||||
|
||||
func newUpdatePostureCheckMacCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckMacCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &updatePostureCheckMacOptions{
|
||||
updatePostureCheckOptions: updatePostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
},
|
||||
addresses: nil,
|
||||
@@ -150,11 +149,11 @@ func runUpdatePostureCheckMac(o *updatePostureCheckMacOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func newUpdatePostureCheckDomainCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckDomainCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &updatePostureCheckDomainOptions{
|
||||
updatePostureCheckOptions: updatePostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
},
|
||||
domains: nil,
|
||||
@@ -184,11 +183,11 @@ func newUpdatePostureCheckDomainCmd(f cmdutil.Factory, out io.Writer, errOut io.
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newUpdatePostureCheckMfaCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckMfaCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &updatePostureCheckMfaOptions{
|
||||
updatePostureCheckOptions: updatePostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
},
|
||||
timeoutSeconds: -1,
|
||||
@@ -332,11 +331,11 @@ func runUpdatePostureCheckDomain(o *updatePostureCheckDomainOptions) error {
|
||||
|
||||
//process
|
||||
|
||||
func newUpdatePostureCheckProcessCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckProcessCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &updatePostureCheckProcessOptions{
|
||||
updatePostureCheckOptions: updatePostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
},
|
||||
hashes: nil,
|
||||
@@ -439,11 +438,11 @@ func runUpdatePostureCheckProcess(o *updatePostureCheckProcessOptions) error {
|
||||
}
|
||||
|
||||
// os
|
||||
func newUpdatePostureCheckOsCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUpdatePostureCheckOsCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &updatePostureCheckOsOptions{
|
||||
updatePostureCheckOptions: updatePostureCheckOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
},
|
||||
os: nil,
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -14,11 +14,10 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -31,10 +30,10 @@ type useOptions struct {
|
||||
}
|
||||
|
||||
// newUseCmd creates the command
|
||||
func newUseCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newUseCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &useOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,19 +14,18 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// newVerifyCmd creates a command object for the "controller verify" command
|
||||
func newVerifyCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newVerifyCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "verify",
|
||||
Short: "verifies various entities managed by the Ziti Edge Controller",
|
||||
@@ -37,7 +36,7 @@ func newVerifyCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newVerifyCaCmd(f, out, errOut))
|
||||
cmd.AddCommand(newVerifyCaCmd(out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
+4
-6
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
nfpem "github.com/openziti/foundation/util/pem"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -60,13 +59,12 @@ type verifyCaOptions struct {
|
||||
}
|
||||
|
||||
// newVerifyCaCmd creates the 'edge controller verify ca' command for the given entity type
|
||||
func newVerifyCaCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newVerifyCaCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &verifyCaOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -14,12 +14,11 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package edge_controller
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -32,10 +31,10 @@ type versionOptions struct {
|
||||
}
|
||||
|
||||
// newVersionCmd creates the command
|
||||
func newVersionCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
func newVersionCmd(out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &versionOptions{
|
||||
edgeOptions: edgeOptions{
|
||||
CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut},
|
||||
CommonOptions: common.CommonOptions{Out: out, Err: errOut},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package edge_controller
|
||||
|
||||
import (
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
)
|
||||
|
||||
// newListCmd creates a command object for the "controller list" command
|
||||
func newDbCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "db",
|
||||
Short: "Database management operations for the Ziti Edge Controller",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newDbSnapshotCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDbCheckIntegrityCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDbCheckIntegrityStatusCmd(f, out, errOut))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
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 edge_controller
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// newDeleteCmd creates a command object for the "edge controller delete" command
|
||||
func newDeleteCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "deletes various entities managed by the Ziti Edge Controller",
|
||||
Long: "deletes various entities managed by the Ziti Edge Controller",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
newOptions := func() *edgeOptions {
|
||||
return &edgeOptions{
|
||||
CommonOptions: common.CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("api-session", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteAuthenticatorCmd("authenticator", newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("ca", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("config", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("config-type", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("edge-router", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("edge-router-policy", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("identity", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service-edge-router-policy", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("service-policy", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("session", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("terminator", runDeleteEntityOfType, newOptions()))
|
||||
cmd.AddCommand(newDeleteCmdForEntityType("posture-check", runDeleteEntityOfType, newOptions()))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type deleteCmdRunner func(*edgeOptions, string) error
|
||||
|
||||
// newDeleteCmdForEntityType creates the delete command for the given entity type
|
||||
func newDeleteCmdForEntityType(entityType string, command deleteCmdRunner, options *edgeOptions) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: entityType + " <id>",
|
||||
Short: "deletes entity of type " + entityType + " managed by the Ziti Edge Controller",
|
||||
Long: "deletes entity of type " + entityType + " managed by the Ziti Edge Controller",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := command(options, getPlural(entityType))
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// runDeleteEntityOfType implements the commands to delete various entity types
|
||||
func runDeleteEntityOfType(o *edgeOptions, entityType string) error {
|
||||
var err error
|
||||
ids := []string{o.Args[0]}
|
||||
if entityType != "terminators" && entityType != "api-sessions" && entityType != "sessions" {
|
||||
ids, err = mapNamesToIDs(entityType, *o, o.Args[0])
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, id := range ids {
|
||||
_, err := util.EdgeControllerDelete(entityType, id, o.Out, o.OutputJSONResponse, o.Timeout, o.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPlural(entityType string) string {
|
||||
if strings.HasSuffix(entityType, "y") {
|
||||
return strings.TrimSuffix(entityType, "y") + "ies"
|
||||
}
|
||||
return entityType + "s"
|
||||
}
|
||||
|
||||
func deleteEntityOfType(entityType string, id string, options *edgeOptions) (*gabs.Container, error) {
|
||||
return util.EdgeControllerDelete(entityType, id, options.Out, options.OutputJSONResponse, options.Timeout, options.Verbose)
|
||||
}
|
||||
@@ -73,7 +73,6 @@ func NewCmdUpgrade(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co
|
||||
cmd.AddCommand(NewCmdUpgradeZitiMgmtGw(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdUpgradeZitiRouter(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdUpgradeZitiTunnel(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdUpgradeZitiEnroller(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdUpgradeZitiProxC(f, out, errOut))
|
||||
cmd.AddCommand(NewCmdUpgradeZitiEdgeTunnel(f, out, errOut))
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiOptions the options for the create spring command
|
||||
type UpgradeZitiOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiOptions struct {
|
||||
// NewCmdUpgradeZiti defines the command
|
||||
func NewCmdUpgradeZiti(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiControllerOptions the options for the upgrade ziti-controller command
|
||||
type UpgradeZitiControllerOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiControllerOptions struct {
|
||||
// NewCmdUpgradeZitiController defines the command
|
||||
func NewCmdUpgradeZitiController(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiControllerOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiEdgeTunnelOptions the options for the upgrade ziti-edge-tunnel command
|
||||
type UpgradeZitiEdgeTunnelOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiEdgeTunnelOptions struct {
|
||||
// NewCmdUpgradeZitiEdgeTunnel defines the command
|
||||
func NewCmdUpgradeZitiEdgeTunnel(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiEdgeTunnelOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
upgradeZitiEnrollerLong = templates.LongDesc(`
|
||||
Upgrades the Ziti Enroller app if there is a newer release
|
||||
`)
|
||||
|
||||
upgradeZitiEnrollerExample = templates.Examples(`
|
||||
# Upgrades the Ziti Enroller app
|
||||
ziti upgrade ziti-enroller
|
||||
`)
|
||||
)
|
||||
|
||||
// UpgradeZitiEnrollerOptions the options for the upgrade ziti-enroller command
|
||||
type UpgradeZitiEnrollerOptions struct {
|
||||
CreateOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
|
||||
// NewCmdUpgradeZitiEnroller defines the command
|
||||
func NewCmdUpgradeZitiEnroller(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiEnrollerOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ziti-enroller",
|
||||
Short: "Upgrades the Ziti Enroller app - if there is a new version available",
|
||||
Aliases: []string{"enroller"},
|
||||
Long: upgradeZitiEnrollerLong,
|
||||
Example: upgradeZitiEnrollerExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.Run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVarP(&options.Version, "version", "v", "", "The specific version to upgrade to")
|
||||
options.addCommonFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run implements the command
|
||||
func (o *UpgradeZitiEnrollerOptions) Run() error {
|
||||
newVersion, err := o.getLatestZitiAppVersion(version.GetBranch(), c.ZITI_ENROLLER)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newVersionStr := newVersion.String()
|
||||
|
||||
if o.Version != "" {
|
||||
newVersionStr = o.Version
|
||||
}
|
||||
|
||||
o.deleteInstalledBinary(c.ZITI_ENROLLER)
|
||||
|
||||
return o.installZitiApp(version.GetBranch(), c.ZITI_ENROLLER, true, newVersionStr)
|
||||
}
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiFabricOptions the options for the upgrade ziti-fabric command
|
||||
type UpgradeZitiFabricOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiFabricOptions struct {
|
||||
// NewCmdUpgradeZitiFabric defines the command
|
||||
func NewCmdUpgradeZitiFabric(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiFabricOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiFabricTestOptions the options for the upgrade ziti-fabric-test command
|
||||
type UpgradeZitiFabricTestOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiFabricTestOptions struct {
|
||||
// NewCmdUpgradeZitiFabricTest defines the command
|
||||
func NewCmdUpgradeZitiFabricTest(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiFabricTestOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiMgmtGwOptions the options for the upgrade ziti-fabric-gw command
|
||||
type UpgradeZitiMgmtGwOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiMgmtGwOptions struct {
|
||||
// NewCmdUpgradeZitiMgmtGw defines the command
|
||||
func NewCmdUpgradeZitiMgmtGw(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiMgmtGwOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiProxCOptions the options for the upgrade ziti-prox-c command
|
||||
type UpgradeZitiProxCOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiProxCOptions struct {
|
||||
// NewCmdUpgradeZitiProxC defines the command
|
||||
func NewCmdUpgradeZitiProxC(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiProxCOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiRouterOptions the options for the upgrade ziti-router command
|
||||
type UpgradeZitiRouterOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiRouterOptions struct {
|
||||
// NewCmdUpgradeZitiRouter defines the command
|
||||
func NewCmdUpgradeZitiRouter(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiRouterOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ package cmd
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/common/version"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates"
|
||||
c "github.com/openziti/ziti/ziti/cmd/ziti/constants"
|
||||
"github.com/openziti/ziti/common/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
|
||||
// UpgradeZitiTunnelOptions the options for the upgrade ziti-tunnel command
|
||||
type UpgradeZitiTunnelOptions struct {
|
||||
CreateOptions
|
||||
CommonOptions
|
||||
|
||||
Version string
|
||||
}
|
||||
@@ -48,12 +48,10 @@ type UpgradeZitiTunnelOptions struct {
|
||||
// NewCmdUpgradeZitiTunnel defines the command
|
||||
func NewCmdUpgradeZitiTunnel(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
options := &UpgradeZitiTunnelOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
CommonOptions: CommonOptions{
|
||||
Factory: f,
|
||||
Out: out,
|
||||
Err: errOut,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -229,81 +229,63 @@ func (o *VersionOptions) versionCheckZitiApp(zitiApp string) error {
|
||||
|
||||
func (o *VersionOptions) upgradeZiti() error {
|
||||
options := &UpgradeZitiOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiController() error {
|
||||
options := &UpgradeZitiControllerOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiFabric() error {
|
||||
options := &UpgradeZitiFabricOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiFabricTest() error {
|
||||
options := &UpgradeZitiFabricTestOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiMgmtGw() error {
|
||||
options := &UpgradeZitiMgmtGwOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiProxC() error {
|
||||
options := &UpgradeZitiProxCOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiRouter() error {
|
||||
options := &UpgradeZitiRouterOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiTunnel() error {
|
||||
options := &UpgradeZitiTunnelOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
func (o *VersionOptions) upgradeZitiEdgeTunnel() error {
|
||||
options := &UpgradeZitiEdgeTunnelOptions{
|
||||
CreateOptions: CreateOptions{
|
||||
CommonOptions: o.CommonOptions,
|
||||
},
|
||||
CommonOptions: o.CommonOptions,
|
||||
}
|
||||
return options.Run()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Exec(program string, colorStdout bool, args ...string) error {
|
||||
p := exec.Command(program, args...)
|
||||
|
||||
stdErrWrapper := &WriterWrapper{
|
||||
c: color.New(color.FgRed),
|
||||
w: os.Stdout,
|
||||
}
|
||||
|
||||
p.Stdin = os.Stdin
|
||||
|
||||
if colorStdout {
|
||||
stdOutWrapper := &WriterWrapper{
|
||||
c: color.New(color.FgBlue),
|
||||
w: os.Stdout,
|
||||
}
|
||||
p.Stdout = stdOutWrapper
|
||||
} else {
|
||||
p.Stdout = os.Stdout
|
||||
}
|
||||
|
||||
p.Stderr = stdErrWrapper
|
||||
if err := p.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Continue(prompt string, defaultValue bool) {
|
||||
resp, err := AskYesNoWithDefault(prompt, defaultValue)
|
||||
if err != nil {
|
||||
fmt.Printf("\nerror: %v. exiting\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !resp {
|
||||
fmt.Print("\nok, exiting\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func AskYesNo(prompt string) (bool, error) {
|
||||
filter := &yesNoFilter{}
|
||||
if _, err := Ask(prompt, filter.Accept); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return filter.result, nil
|
||||
}
|
||||
|
||||
func AskYesNoWithDefault(prompt string, defaultVal bool) (bool, error) {
|
||||
filter := &yesNoDefaultFilter{
|
||||
defaultVal: defaultVal,
|
||||
}
|
||||
if _, err := Ask(prompt, filter.Accept); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return filter.result, nil
|
||||
}
|
||||
|
||||
func Ask(prompt string, f func(string) bool) (string, error) {
|
||||
for {
|
||||
val, err := term.Prompt(prompt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
val = strings.TrimSpace(val)
|
||||
if f(val) {
|
||||
return val, nil
|
||||
}
|
||||
fmt.Printf("Invalid input: %v\n", val)
|
||||
}
|
||||
}
|
||||
|
||||
type yesNoFilter struct {
|
||||
result bool
|
||||
}
|
||||
|
||||
func (self *yesNoFilter) Accept(s string) bool {
|
||||
if strings.EqualFold("y", s) || strings.EqualFold("yes", s) {
|
||||
self.result = true
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.EqualFold("n", s) || strings.EqualFold("no", s) {
|
||||
self.result = false
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type yesNoDefaultFilter struct {
|
||||
result bool
|
||||
defaultVal bool
|
||||
}
|
||||
|
||||
func (self *yesNoDefaultFilter) Accept(s string) bool {
|
||||
if s == "" {
|
||||
self.result = self.defaultVal
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.EqualFold("y", s) || strings.EqualFold("yes", s) {
|
||||
self.result = true
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.EqualFold("n", s) || strings.EqualFold("no", s) {
|
||||
self.result = false
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type WriterWrapper struct {
|
||||
c *color.Color
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (self *WriterWrapper) Write(p []byte) (n int, err error) {
|
||||
return self.c.Fprint(self.w, string(p))
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func ParseArgumentsWithStrings(val string) []string {
|
||||
var result []string
|
||||
|
||||
current := &strings.Builder{}
|
||||
inString := false
|
||||
for _, r := range val {
|
||||
if r == '\'' {
|
||||
if inString {
|
||||
inString = false
|
||||
} else {
|
||||
inString = true
|
||||
}
|
||||
} else if !inString && unicode.IsSpace(r) {
|
||||
if current.Len() > 0 {
|
||||
result = append(result, current.String())
|
||||
current.Reset()
|
||||
}
|
||||
} else {
|
||||
current.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
if current.Len() > 0 {
|
||||
result = append(result, current.String())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseArgumentsWithStrings(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "one",
|
||||
args: "one two three 'four five'",
|
||||
want: []string{"one", "two", "three", "four five"},
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
args: " one two three 'four five' ",
|
||||
want: []string{"one", "two", "three", "four five"},
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
args: " one two three 'four \"five\"' ",
|
||||
want: []string{"one", "two", "three", "four \"five\""},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ParseArgumentsWithStrings(tt.args); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseArgumentsWithStrings() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
markdown "github.com/MichaelMure/go-term-markdown"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/valyala/fasttemplate"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
codeActionBlockStart = "```action:"
|
||||
codeActionBlockEnd = "```"
|
||||
commentActionBlockStart = "<!---action:"
|
||||
commentActionBlockEnd = "-->"
|
||||
actionMarker = "f572d396fae9206628714fb2ce00f72e94f2258f"
|
||||
)
|
||||
|
||||
func NewRunner() *Runner {
|
||||
result := &Runner{
|
||||
actionHandlers: map[string]ActionHandler{},
|
||||
variables: map[string]interface{}{},
|
||||
LineWidth: 75,
|
||||
LeftPad: 5,
|
||||
NewLinePause: time.Millisecond * 20,
|
||||
}
|
||||
result.RegisterActionHandlerF("echo", func(ctx *ActionContext) error {
|
||||
fmt.Printf("echo: %v", ctx.Body)
|
||||
return nil
|
||||
})
|
||||
result.RegisterActionHandlerF("userInput", result.HandlePromptForInput)
|
||||
result.RegisterActionHandlerF("pause", result.HandlePause)
|
||||
return result
|
||||
}
|
||||
|
||||
type ActionContext struct {
|
||||
Action string
|
||||
Headers map[string]string
|
||||
Body string
|
||||
Runner *Runner
|
||||
}
|
||||
|
||||
type ActionHandler interface {
|
||||
Execute(ctx *ActionContext) error
|
||||
}
|
||||
|
||||
type ActionHandlerF func(ctx *ActionContext) error
|
||||
|
||||
func (self ActionHandlerF) Execute(ctx *ActionContext) error {
|
||||
return self(ctx)
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
LineWidth int
|
||||
LeftPad int
|
||||
NewLinePause time.Duration
|
||||
AssumeDefault bool
|
||||
actionHandlers map[string]ActionHandler
|
||||
actions []func() error
|
||||
variables map[string]interface{}
|
||||
}
|
||||
|
||||
func (self *Runner) AddVariable(name string, val interface{}) {
|
||||
self.variables[name] = val
|
||||
}
|
||||
|
||||
func (self *Runner) Run(source []byte) error {
|
||||
markdownSource, err := self.transformSource(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
renderedMarkdown := markdown.Render(string(markdownSource), self.LineWidth, self.LeftPad)
|
||||
return self.runMarkdown(renderedMarkdown)
|
||||
}
|
||||
|
||||
func (self *Runner) runMarkdown(source []byte) error {
|
||||
fmt.Println("")
|
||||
pauseWriter := NewSlowWriter(self.NewLinePause)
|
||||
|
||||
for {
|
||||
next := bytes.Index(source, []byte(actionMarker))
|
||||
if next < 0 {
|
||||
if err := self.EmitTemplatized(string(source), pauseWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("")
|
||||
return nil
|
||||
}
|
||||
if next == 0 {
|
||||
source = source[len(actionMarker):]
|
||||
action := self.nextAction()
|
||||
if err := action(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
md := source[0:next]
|
||||
if err := self.EmitTemplatized(string(md), pauseWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
source = source[next:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Runner) nextAction() func() error {
|
||||
result := self.actions[0]
|
||||
self.actions = self.actions[1:]
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *Runner) transformSource(source []byte) ([]byte, error) {
|
||||
var result []byte
|
||||
for {
|
||||
if len(source) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var behavior parseBehavior
|
||||
if CodeAction.IsStarting(source) {
|
||||
behavior = CodeAction
|
||||
} else if CommentAction.IsStarting(source) {
|
||||
behavior = CommentAction
|
||||
}
|
||||
|
||||
if behavior != nil {
|
||||
source = source[len(behavior.GetStartToken()):]
|
||||
endIndex := bytes.Index(source, []byte(behavior.GetEndToken()))
|
||||
if endIndex < 0 {
|
||||
return nil, errors.Errorf("no end %v found for action block", behavior.GetEndToken())
|
||||
}
|
||||
actionSource := source[:endIndex]
|
||||
source = source[endIndex+len(behavior.GetEndToken()):]
|
||||
|
||||
var actionHeader, body string
|
||||
|
||||
nlIndex := bytes.IndexByte(actionSource, '\n')
|
||||
if nlIndex < 1 {
|
||||
actionHeader = string(actionSource)
|
||||
} else {
|
||||
actionHeader = strings.TrimSpace(string(actionSource[:nlIndex]))
|
||||
body = strings.TrimSpace(string(actionSource[nlIndex+1 : endIndex]))
|
||||
}
|
||||
actionDef := strings.TrimSpace(actionHeader)
|
||||
action, headers := self.parseAction(actionDef)
|
||||
|
||||
handler, ok := self.actionHandlers[action]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("no handler found for action: %v. Available: %+v", action, self.actionIds())
|
||||
}
|
||||
ctx := &ActionContext{
|
||||
Action: action,
|
||||
Headers: headers,
|
||||
Body: body,
|
||||
Runner: self,
|
||||
}
|
||||
self.actions = append(self.actions, func() error {
|
||||
return handler.Execute(ctx)
|
||||
})
|
||||
|
||||
result = append(result, []byte(actionMarker)...)
|
||||
} else {
|
||||
result = append(result, source[0])
|
||||
source = source[1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Runner) parseAction(s string) (string, map[string]string) {
|
||||
var action string
|
||||
headers := map[string]string{}
|
||||
|
||||
idx := strings.IndexByte(s, ' ')
|
||||
if idx < 1 {
|
||||
return s, headers
|
||||
}
|
||||
|
||||
action = s[:idx]
|
||||
rest := s[idx+1:]
|
||||
for _, kv := range strings.Split(rest, " ") {
|
||||
vals := strings.Split(kv, "=")
|
||||
if len(vals) < 2 {
|
||||
headers[vals[0]] = ""
|
||||
} else {
|
||||
headers[vals[0]] = vals[1]
|
||||
}
|
||||
}
|
||||
return action, headers
|
||||
}
|
||||
|
||||
func (self *Runner) actionIds() []string {
|
||||
var result []string
|
||||
for k := range self.actionHandlers {
|
||||
result = append(result, k)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *Runner) RegisterActionHandler(action string, handler ActionHandler) {
|
||||
self.actionHandlers[action] = handler
|
||||
}
|
||||
|
||||
func (self *Runner) RegisterActionHandlerF(action string, handler func(ctx *ActionContext) error) {
|
||||
self.actionHandlers[action] = ActionHandlerF(handler)
|
||||
}
|
||||
|
||||
func (self *Runner) LeftPadBuilder(b *strings.Builder) {
|
||||
for i := 0; i < self.LeftPad; i++ {
|
||||
b.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Runner) EmitTemplatized(s string, out io.Writer) error {
|
||||
_, err := fasttemplate.ExecuteFunc(s, "${", "}", out, func(w io.Writer, tag string) (int, error) {
|
||||
tag = strings.ReplaceAll(tag, "\n", "") // in case we hit a line-break
|
||||
tag = strings.ReplaceAll(tag, " ", "") // in case we hit a line-break
|
||||
|
||||
val, ok := self.variables[tag]
|
||||
if !ok {
|
||||
return 0, errors.Errorf("unknown template value: '%v'", tag)
|
||||
}
|
||||
buf := []byte(fmt.Sprintf("%v", val))
|
||||
return w.Write(buf)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *Runner) Template(s string) (string, error) {
|
||||
buf := &strings.Builder{}
|
||||
_, err := fasttemplate.ExecuteFunc(s, "${", "}", buf, func(w io.Writer, tag string) (int, error) {
|
||||
val, ok := self.variables[tag]
|
||||
if !ok {
|
||||
return 0, errors.Errorf("unknown template value: '%v'", tag)
|
||||
}
|
||||
buf := []byte(fmt.Sprintf("%v", val))
|
||||
return w.Write(buf)
|
||||
})
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func (self *Runner) HandlePromptForInput(ctx *ActionContext) error {
|
||||
varName, ok := ctx.Headers["variable"]
|
||||
if !ok {
|
||||
return errors.New("prompt must specify which variable to set")
|
||||
}
|
||||
var val string
|
||||
var err error
|
||||
for val == "" {
|
||||
val, err = term.Prompt(ctx.Body + " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx.Runner.AddVariable(varName, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Runner) HandlePause(*ActionContext) error {
|
||||
if !self.AssumeDefault {
|
||||
c := color.New(color.FgHiWhite, color.Bold)
|
||||
_, err := term.Prompt(c.Sprintf("Press enter to continue: "))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type parseBehavior interface {
|
||||
IsStarting(source []byte) bool
|
||||
GetStartToken() string
|
||||
GetEndToken() string
|
||||
}
|
||||
|
||||
type CodeActionBlock struct{}
|
||||
|
||||
func (self CodeActionBlock) IsStarting(source []byte) bool {
|
||||
return startsWith(source, []byte(codeActionBlockStart))
|
||||
}
|
||||
|
||||
func (self CodeActionBlock) GetStartToken() string {
|
||||
return codeActionBlockStart
|
||||
}
|
||||
|
||||
func (self CodeActionBlock) GetEndToken() string {
|
||||
return codeActionBlockEnd
|
||||
}
|
||||
|
||||
type CommentActionBlock struct{}
|
||||
|
||||
func (self CommentActionBlock) IsStarting(source []byte) bool {
|
||||
return startsWith(source, []byte(commentActionBlockStart))
|
||||
}
|
||||
|
||||
func (self CommentActionBlock) GetStartToken() string {
|
||||
return commentActionBlockStart
|
||||
}
|
||||
|
||||
func (self CommentActionBlock) GetEndToken() string {
|
||||
return commentActionBlockEnd
|
||||
}
|
||||
|
||||
func startsWith(b []byte, val []byte) bool {
|
||||
if len(b) < len(val) {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(b[:len(val)], val)
|
||||
}
|
||||
|
||||
var CodeAction = CodeActionBlock{}
|
||||
var CommentAction = CommentActionBlock{}
|
||||
@@ -0,0 +1,64 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/alecthomas/chroma/quick"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewShowActionHandler() *ShowActionHandler {
|
||||
return &ShowActionHandler{
|
||||
data: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
type ShowActionHandler struct {
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (self *ShowActionHandler) Execute(ctx *ActionContext) error {
|
||||
name, ok := ctx.Headers["src"]
|
||||
if !ok {
|
||||
return errors.New("no name specified in show")
|
||||
}
|
||||
|
||||
content, ok := self.data[name]
|
||||
if !ok {
|
||||
return errors.Errorf("no contents found to show for name: '%v'", name)
|
||||
}
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
view, err := AskYesNoWithDefault(fmt.Sprintf("View source for %v? [Y/N] (default N): ", name), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !view {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
codeWriter := NewSlowWriter(ctx.Runner.NewLinePause)
|
||||
|
||||
fmt.Println("")
|
||||
fmt.Printf("%v:\n", name)
|
||||
for i := 0; i < 80; i++ {
|
||||
fmt.Print("-")
|
||||
}
|
||||
fmt.Println("")
|
||||
if lang, found := ctx.Headers["highlight"]; found {
|
||||
if err := quick.Highlight(codeWriter, content, lang, "terminal", "friendly"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, _ = fmt.Fprintln(codeWriter, content)
|
||||
}
|
||||
for i := 0; i < 80; i++ {
|
||||
fmt.Print("-")
|
||||
}
|
||||
fmt.Println("")
|
||||
return ctx.Runner.HandlePause(ctx)
|
||||
}
|
||||
|
||||
func (self *ShowActionHandler) Add(name, contents string) {
|
||||
self.data[name] = contents
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package tutorial
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewSlowWriter(newlinePause time.Duration) io.Writer {
|
||||
return &slowWriter{
|
||||
delay: newlinePause,
|
||||
}
|
||||
}
|
||||
|
||||
type slowWriter struct {
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
func (self *slowWriter) Write(p []byte) (n int, err error) {
|
||||
var buf []byte
|
||||
written := 0
|
||||
for _, b := range p {
|
||||
buf = append(buf, b)
|
||||
if b == '\n' {
|
||||
time.Sleep(self.delay)
|
||||
n, err := os.Stdout.Write(buf)
|
||||
buf = buf[0:0]
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) > 0 {
|
||||
n, err := os.Stdout.Write(buf)
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
@@ -26,6 +26,7 @@ func (self *RestClientConfig) GetIdentity() string {
|
||||
|
||||
type RestClientIdentity struct {
|
||||
Url string `json:"url"`
|
||||
Username string `json:"username"`
|
||||
Token string `json:"token"`
|
||||
LoginTime string `json:"loginTime"`
|
||||
Cert string `json:"cert,omitempty"`
|
||||
|
||||
@@ -675,7 +675,7 @@ func EdgeControllerList(path string, params url.Values, logJSON bool, out io.Wri
|
||||
}
|
||||
|
||||
resp, err := client.
|
||||
SetTimeout(time.Duration(time.Duration(timeout)*time.Second)).
|
||||
SetTimeout(time.Duration(timeout)*time.Second).
|
||||
SetDebug(verbose).
|
||||
R().
|
||||
SetHeader("Content-Type", "application/json").
|
||||
@@ -886,7 +886,7 @@ func (e EdgeManagementAuth) AuthenticateRequest(request openApiRuntime.ClientReq
|
||||
}
|
||||
|
||||
// EdgeControllerCreate will create entities of the given type in the given Edge Controller
|
||||
func EdgeControllerCreate(entityType string, body string, out io.Writer, logJSON bool, timeout int, verbose bool) (*gabs.Container, error) {
|
||||
func EdgeControllerCreate(entityType string, body string, out io.Writer, logRequestJson, logResponseJson bool, timeout int, verbose bool) (*gabs.Container, error) {
|
||||
restClientIdentity, err := LoadSelectedRWIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -897,6 +897,14 @@ func EdgeControllerCreate(entityType string, body string, out io.Writer, logJSON
|
||||
if restClientIdentity.Cert != "" {
|
||||
client.SetRootCertificate(restClientIdentity.Cert)
|
||||
}
|
||||
|
||||
url := restClientIdentity.GetBaseUrl() + "/" + entityType
|
||||
if logRequestJson {
|
||||
fmt.Printf("%v to %v\n", "POST", url)
|
||||
outputJson(out, []byte(body))
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
resp, err := client.
|
||||
SetTimeout(time.Duration(timeout)*time.Second).
|
||||
SetDebug(verbose).
|
||||
@@ -904,7 +912,7 @@ func EdgeControllerCreate(entityType string, body string, out io.Writer, logJSON
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader(constants.ZitiSession, restClientIdentity.Token).
|
||||
SetBody(body).
|
||||
Post(restClientIdentity.GetBaseUrl() + "/" + entityType)
|
||||
Post(url)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create %v instance in Ziti Edge Controller at %v. Error: %v", entityType, restClientIdentity.Url, err)
|
||||
@@ -915,7 +923,7 @@ func EdgeControllerCreate(entityType string, body string, out io.Writer, logJSON
|
||||
entityType, restClientIdentity.GetBaseUrl(), resp.Status(), prettyPrintResponse(resp))
|
||||
}
|
||||
|
||||
if logJSON {
|
||||
if logResponseJson {
|
||||
outputJson(out, resp.Body())
|
||||
}
|
||||
|
||||
@@ -929,7 +937,7 @@ func EdgeControllerCreate(entityType string, body string, out io.Writer, logJSON
|
||||
}
|
||||
|
||||
// EdgeControllerDelete will delete entities of the given type in the given Edge Controller
|
||||
func EdgeControllerDelete(entityType string, id string, out io.Writer, logJSON bool, timeout int, verbose bool) (*gabs.Container, error) {
|
||||
func EdgeControllerDelete(entityType string, id string, out io.Writer, logResponseJson bool, timeout int, verbose bool) (*gabs.Container, error) {
|
||||
restClientIdentity, err := LoadSelectedRWIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -960,7 +968,7 @@ func EdgeControllerDelete(entityType string, id string, out io.Writer, logJSON b
|
||||
entityPath, restClientIdentity.GetBaseUrl(), resp.Status(), prettyPrintResponse(resp))
|
||||
}
|
||||
|
||||
if logJSON {
|
||||
if logResponseJson {
|
||||
outputJson(out, resp.Body())
|
||||
}
|
||||
|
||||
@@ -986,7 +994,10 @@ func EdgeControllerUpdate(entityType string, body string, out io.Writer, method
|
||||
client.SetRootCertificate(restClientIdentity.Cert)
|
||||
}
|
||||
|
||||
url := restClientIdentity.GetBaseUrl() + "/" + entityType
|
||||
|
||||
if logRequestJson {
|
||||
fmt.Printf("%v to %v\n", method, url)
|
||||
outputJson(out, []byte(body))
|
||||
fmt.Println()
|
||||
}
|
||||
@@ -998,7 +1009,7 @@ func EdgeControllerUpdate(entityType string, body string, out io.Writer, method
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader(constants.ZitiSession, restClientIdentity.Token).
|
||||
SetBody(body).
|
||||
Execute(method, restClientIdentity.GetBaseUrl()+"/"+entityType)
|
||||
Execute(method, url)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to update %v instance in Ziti Edge Controller at %v. Error: %v", entityType, restClientIdentity.GetBaseUrl(), err)
|
||||
|
||||
Reference in New Issue
Block a user