diff --git a/.travis.yml b/.travis.yml index c2496ea9c..28f402ccd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,11 +32,12 @@ jobs: - stage: "Build and Test" os: linux arch: arm64 + dist: bionic env: GOX_OS=linux script: - set -e - sudo dpkg --add-architecture armhf - - sudo apt-get update -yq + - sudo apt-get update -yq - |- sudo apt-get -yq install \ crossbuild-essential-armhf \ diff --git a/README.md b/README.md index 43e72b3da..3bdcdf4d9 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,3 @@ Ziti is a modern, programmable network overlay with associated edge components, for application-embedded, zero trust network connectivity, written by developers for developers. Ziti allows developers to take control of networking while with secure connectivity and advanced security concepts such as Zero Trust. This repository contains the executables as configured in the open-core release of Ziti. The underlying `ziti-edge` and `ziti-fabric` components are rolled up and configured into the binaries that we ship. - -Currently working through migrating our internal repositories over to GitHub. Stay tuned. \ No newline at end of file diff --git a/doc/release-notes-0.12.md b/doc/release-notes-0.12.md new file mode 100644 index 000000000..c645b71f6 --- /dev/null +++ b/doc/release-notes-0.12.md @@ -0,0 +1,156 @@ +This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.11.x to version 0.12.x + +# Theme +Ziti 0.12 includes the following: + + * Terminators have been extracted from services + * Terminators define where a service terminates. Previously each service had exactly one terminator. Now services can have 0 to N terminators. + * List APIs now support inline paging + * Association APIs now support filtering, paging and querying + * The bolt datastore creates a backup of the datastore file before attempting a schema/data migration + * Fabric and edge code are now much more closely aligned at the persistence and model layers + * Some deprecated endpoints are now being removed + +# Terminators +See https://github.com/netfoundry/ziti-fabric/wiki/Pluggable-Service-Terminators for a discussion of what serivice terminators are, the motivation for extracting them from services and the design for how they will work. + +This release includes the following: + + * Terminators extracted from service as separate entities + * When SDK applications bind and unbind, the controller now dynamically adds/removes terminators as appropriate + +This release does not yet include a terminator strategy API. Strategies can be specified per service, but if a service has multiple terminators the first one will be used. The terminator strategy API along with some implementations will be added in a follow-up release. This release also does not include strategy inputs on terminators as discussed in the above design document. If strategy inputs end up being useful, they may be added in the furure. + +## Terminator related API changes + +There is a new terminators endpoint: + + * Endpoint: /terminators + * Supported operations + * Detail: GET /terminators/ + * List: GET /terminators/ + * Create: POST /terminators + * Update All Fields: PUT /terminators/ + * Update Selective Fields: PATCH /terminators/ + * Delete: DELETE /terminators/ + * Properties + * Terminators support the standard properties (id, createdAt, updatedAt, tags) + * service - type: uuid, must be a valid service id + * router - type: uuid, must be a valid router id + * binding - type: string. Optional, defaults to "transport". The xgress binding on the selected router to use + * address - type: string. The address that will be dialed using the xgress component on the selected router + +The service endpoint has changes as well: + + * Endpoint: /services + * New operations + * Query related endpoints: GET /services//terminators?filter= + * The following properties have been removed + * egressRouter + * endpointAddress + * The following property has been added + * terminatorStrategy - type: string, optional. The terminator strategy to use. Currently unused. + +The fabric service definition has also changed (visible from ziti-fabric). + + * The following properties have been removed + * `binding` + * `egressRouter` + * `endpointAddress` + * The following property has been added + * `terminatorStrategy` + +The ziti and ziti-fabric CLIs have been updated with new terminator related functionality, so that terminators can be viewed, created and deleted from both. + +# Filtering/Sorting/Paging Changes +List operations on entities previously allowed the following parameters: + + * `filter` + * `sort` + * `limit` + * `offset` + +These are all still supported, but now sort, limit and offset can also be included in the filter. If parameters are specified both in the filter and in an explicit query parameter, the filter takes precedence. + +When listing entities from the ziti CLI, filters can be included as an optional argument. + +For example: + + $ ziti edge controller list services + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: 9480e39d-0664-4482-b230-5da2c17b225b name: iperf terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + id: dc0446f0-7eaa-465f-80b5-c88f0a6b59cc name: grpc-ping terminator strategy: role attributes: ["fortio","fortio-server"] + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s"' + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s" sort by name' + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s" sort by name skip 1 limit 2' + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + +Association lists now also support filtering, sorting and paging. Association GET operations only support the filter parameter. + + + $ ziti edge controller list service terminators ssh + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + + $ ziti edge controller list service terminators ssh "true sort by address" + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + + $ ziti edge controller list service terminators ssh "true sort by address desc" + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + +# Bolt Datastore Migrations +The fabric now supports migrating schema/data from one version to another. The fabric and edge share a common framework for migration. The migration framework now also automatically backs up the bolt data file before migration data. The backup file will have the same name as the original bolt file but with a timestamp appended to it. + +Example: + + Original file: /tmp/ziti-bolt.db + Backup file: /tmp/ziti-bolt.db-20200316-134725 + +The fabric and edge schemas do not yet get migrated in the same transaction. This will be addressed in a follow-up release. + +# Fabric and Edge Alignment +The fabric and edge persistence and model layers are now using the same foundational plumbing. This will allow for a common API layer in a follow-up release. + +As part of this consolidation effort, fabric entities now share the same set of common properties as edge entities, namely: + + * `id` + * `createdAt` + * `updatedAt` + * `tags` + +Previously the only common property was `id`. + +# Deprecated Endpoints +The `/gateways` (replaced by `/edge-routers`) and `network-sessions` (replaced by `/sessions`) endpoints, which were previously deprecated, have now been removed. + +# Miscellaneous + +There is a new `ziti edge controller version` command which shows information about the version of the controller being connected to: + +Example: + + $ ziti edge controller version + Version : v0.9.0 + GIT revision: ea556fc18740 + Build Date : 2020-02-11 16:09:08 + Runtime : go1.13 diff --git a/go.mod b/go.mod index 881a4417c..51e86e68a 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.0.0-20190813191113-2be43bd0dccc - github.com/netfoundry/ziti-edge v0.11.0 + github.com/netfoundry/ziti-edge v0.12.0 github.com/netfoundry/ziti-fabric v0.11.1 github.com/netfoundry/ziti-foundation v0.7.0 github.com/netfoundry/ziti-sdk-golang v0.11.1 diff --git a/go.sum b/go.sum index da374a535..f7bd628e9 100644 --- a/go.sum +++ b/go.sum @@ -222,14 +222,12 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/netfoundry/secretstream v0.1.1 h1:z6T7B5DuOtr9O+SmKaS9DzwOoGLYtgvyTzuPuR5FO7I= github.com/netfoundry/secretstream v0.1.1/go.mod h1:uasYkYSp0MmNSlKOWJ2sVzxPms8e58TS4ENq4yro86k= -github.com/netfoundry/ziti-edge v0.11.0 h1:YxSyo+odKyVZcyHRNVYyi/PKczVUMTTp/HkRdez0xoY= -github.com/netfoundry/ziti-edge v0.11.0/go.mod h1:RNx5IpKa21kQwDbkLISCMq4RraN4MnLIvD44eY84vLA= -github.com/netfoundry/ziti-fabric v0.10.0 h1:AdYcZengrJzmgCx6E0Uxd9YdFwUkSvxlP5AFNgkp4UE= -github.com/netfoundry/ziti-fabric v0.10.0/go.mod h1:wIwkusCaTJeIr+7ojELcG/wKFA/BhleQX68Ft/91ASs= -github.com/netfoundry/ziti-foundation v0.6.5 h1:csIX4eMBM8p/UvoDioBByGpqOAxA3Wn2dOPY1xaGLSE= -github.com/netfoundry/ziti-foundation v0.6.5/go.mod h1:D2kU4O23O3Ll+v34tidLYr/jNhigiHM0Mz8fKuIJu7E= -github.com/netfoundry/ziti-sdk-golang v0.11.0 h1:nx+dPme/gasknswOFkUS++ZATncF8Yb0tcOmlV1E2V4= -github.com/netfoundry/ziti-sdk-golang v0.11.0/go.mod h1:aUgEuA/gse9E+hXldo2WioP4KoxyJjxZTjHieHLs5C8= +github.com/netfoundry/ziti-edge v0.12.0 h1:NU/PE5hYNr4A9dCqSmEpDihKHYbW9E5G+R+3If3nFkA= +github.com/netfoundry/ziti-edge v0.12.0/go.mod h1:/50mZCqBHDTsX7RN84qPGjiveWbzF0knL75DzZOmwD0= +github.com/netfoundry/ziti-fabric v0.11.0 h1:4GQqtsK1VWnMVEth6EPkvua/YX0AOC3UAn4/EiEbvKA= +github.com/netfoundry/ziti-fabric v0.11.0/go.mod h1:kjtZ81Matol9D/HL05MG+/l8BceQ+0eayWaU6LQo9js= +github.com/netfoundry/ziti-foundation v0.7.0 h1:Lrcq88sosUg0w0lwO4iU0ksiFB1q6H4ZPf7vUMLtPas= +github.com/netfoundry/ziti-foundation v0.7.0/go.mod h1:MK2ajCpS40MtiZFnMYjKIBDTQFDWwgqNq+RxypNjl9U= github.com/netfoundry/ziti-sdk-golang v0.11.1 h1:TqCEGo4d3yBQ8a5MLJBrgWvlRd0BtaB2wJk7uXMlW8w= github.com/netfoundry/ziti-sdk-golang v0.11.1/go.mod h1:BSP+tnw+s1qp7DcjoifofQtpkkgt7mwDoPSIe9D7w8s= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -416,6 +414,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= diff --git a/quickstart/local/test-ziti.sh b/quickstart/local/test-ziti.sh index 06345a193..7334e353e 100644 --- a/quickstart/local/test-ziti.sh +++ b/quickstart/local/test-ziti.sh @@ -1,6 +1,8 @@ ziti edge controller create config netcat ziti-tunneler-client.v1 '{ "hostname" : "localhost", "port" : 7256 }' -ziti edge controller create service netcat7256 "${ZITI_ROUTER_BR_HOSTNAME}" tcp://localhost:7256 --configs netcat +ziti edge controller create service netcat7256 --configs netcat + +ziti edge controller create terminator netcat7256 "${ZITI_ROUTER_BR_HOSTNAME}" tcp://localhost:7256 ziti edge controller create identity device "test_identity" -o "${ZITI_HOME}/test_identity".jwt diff --git a/version b/version index 51176c7c8..c43e1055f 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.11 +0.12 diff --git a/ziti-fabric-gw/subcmd/create_service.go b/ziti-fabric-gw/subcmd/create_service.go index 1e2e020ab..d886958d9 100644 --- a/ziti-fabric-gw/subcmd/create_service.go +++ b/ziti-fabric-gw/subcmd/create_service.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,11 +17,11 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" "encoding/json" "github.com/golang/protobuf/proto" "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "net/http" ) @@ -41,10 +41,12 @@ func handleCreateService(w http.ResponseWriter, req *http.Request) { request := &mgmt_pb.CreateServiceRequest{ Service: &mgmt_pb.Service{ - Id: svc.Id, - Binding: svc.Binding, - EndpointAddress: svc.EndpointAddress, - Egress: svc.Egress, + Id: svc.Id, + Terminators: []*mgmt_pb.Terminator{{ + RouterId: svc.Egress, + Binding: svc.Binding, + Address: svc.EndpointAddress, + }}, }, } body, err := proto.Marshal(request) diff --git a/ziti-fabric-gw/subcmd/get_service.go b/ziti-fabric-gw/subcmd/get_service.go index fe0c15984..f3ff152ef 100644 --- a/ziti-fabric-gw/subcmd/get_service.go +++ b/ziti-fabric-gw/subcmd/get_service.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,12 +17,12 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" "encoding/json" "github.com/golang/protobuf/proto" "github.com/gorilla/mux" "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "net/http" "time" ) @@ -94,10 +94,16 @@ func handleGetService(w http.ResponseWriter, req *http.Request) { func convertService(svc *mgmt_pb.Service) interface{} { d := &data{Data: make([]interface{}, 0)} + address := "" + router := "" + if len(svc.Terminators) > 0 { + address = svc.Terminators[0].Address + router = svc.Terminators[0].RouterId + } d.Data = append(d.Data, &service{ Id: svc.Id, - EndpointAddress: svc.EndpointAddress, - Egress: svc.Egress, + EndpointAddress: address, + Egress: router, }) return d } diff --git a/ziti-fabric-gw/subcmd/list_services.go b/ziti-fabric-gw/subcmd/list_services.go index 770cd3583..3ef0ca3eb 100644 --- a/ziti-fabric-gw/subcmd/list_services.go +++ b/ziti-fabric-gw/subcmd/list_services.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,11 +17,11 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" "encoding/json" "github.com/golang/protobuf/proto" "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "net/http" "time" ) @@ -75,10 +75,16 @@ func handleListServices(w http.ResponseWriter, req *http.Request) { func convertServices(in []*mgmt_pb.Service) interface{} { d := &data{Data: make([]interface{}, 0)} for _, svc := range in { + address := "" + router := "" + if len(svc.Terminators) > 0 { + address = svc.Terminators[0].Address + router = svc.Terminators[0].RouterId + } d.Data = append(d.Data, &service{ Id: svc.Id, - EndpointAddress: svc.EndpointAddress, - Egress: svc.Egress, + EndpointAddress: address, + Egress: router, }) } return d diff --git a/ziti-fabric/subcmd/create_service.go b/ziti-fabric/subcmd/create_service.go index 96e8187ca..0dd8858cf 100644 --- a/ziti-fabric/subcmd/create_service.go +++ b/ziti-fabric/subcmd/create_service.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,33 +17,33 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" - "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "github.com/spf13/cobra" "time" ) +var createServiceClient *mgmtClient +var createServiceTerminatorStrategy string + func init() { - createService.Flags().StringVar(&createServiceBinding, "binding", "transport", "Xgress binding for service") + createService.Flags().StringVar(&createServiceTerminatorStrategy, "terminator-strategy", "", "Terminator strategy for service") createServiceClient = NewMgmtClient(createService) createCmd.AddCommand(createService) } var createService = &cobra.Command{ - Use: "service ", + Use: "service ", Short: "Create a new fabric service", - Args: cobra.ExactArgs(3), + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { if ch, err := createServiceClient.Connect(); err == nil { request := &mgmt_pb.CreateServiceRequest{ Service: &mgmt_pb.Service{ - Id: args[0], - Binding: createServiceBinding, - EndpointAddress: args[1], - Egress: args[2], + Id: args[0], + TerminatorStrategy: createServiceTerminatorStrategy, }, } body, err := proto.Marshal(request) @@ -51,30 +51,22 @@ var createService = &cobra.Command{ panic(err) } requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_CreateServiceRequestType), body) - waitCh, err := ch.SendAndWait(requestMsg) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) if err != nil { panic(err) } - select { - case responseMsg := <-waitCh: - if responseMsg.ContentType == channel2.ContentTypeResultType { - result := channel2.UnmarshalResult(responseMsg) - if result.Success { - fmt.Printf("\nsuccess\n\n") - } else { - fmt.Printf("\nfailure [%s]\n\n", result.Message) - } + if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") } else { - panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + fmt.Printf("\nfailure [%s]\n\n", result.Message) } - case <-time.After(5 * time.Second): - panic(errors.New("timeout")) + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) } - } else { panic(err) } }, } -var createServiceClient *mgmtClient -var createServiceBinding string diff --git a/ziti-fabric/subcmd/create_terminator.go b/ziti-fabric/subcmd/create_terminator.go new file mode 100644 index 000000000..540444a32 --- /dev/null +++ b/ziti-fabric/subcmd/create_terminator.go @@ -0,0 +1,74 @@ +/* + Copyright 2020 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package subcmd + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/spf13/cobra" + "time" +) + +var createTerminatorClient *mgmtClient +var createTerminatorBinding string + +func init() { + createTerminator.Flags().StringVar(&createTerminatorBinding, "binding", "transport", "Terminator binding") + createTerminatorClient = NewMgmtClient(createTerminator) + createCmd.AddCommand(createTerminator) +} + +var createTerminator = &cobra.Command{ + Use: "terminator
", + Short: "Create a new fabric service terminator", + Args: cobra.ExactArgs(3), + Run: func(cmd *cobra.Command, args []string) { + if ch, err := createTerminatorClient.Connect(); err == nil { + request := &mgmt_pb.CreateTerminatorRequest{ + Terminator: &mgmt_pb.Terminator{ + ServiceId: args[0], + RouterId: args[1], + Binding: createTerminatorBinding, + Address: args[2], + }, + } + body, err := proto.Marshal(request) + if err != nil { + panic(err) + } + requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_CreateTerminatorRequestType), body) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) + if err != nil { + panic(err) + } + if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") + } else { + fmt.Printf("\nfailure [%s]\n\n", result.Message) + } + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + } + } else { + panic(err) + } + }, +} diff --git a/ziti-fabric/subcmd/get_service.go b/ziti-fabric/subcmd/get_service.go index 75f8f16f5..3f339ce36 100644 --- a/ziti-fabric/subcmd/get_service.go +++ b/ziti-fabric/subcmd/get_service.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,11 +17,10 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" - "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "github.com/spf13/cobra" "time" ) @@ -45,40 +44,36 @@ var getService = &cobra.Command{ panic(err) } requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_GetServiceRequestType), body) - waitCh, err := ch.SendAndWait(requestMsg) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) if err != nil { panic(err) } - select { - case responseMsg := <-waitCh: - if responseMsg.ContentType == int32(mgmt_pb.ContentType_GetServiceResponseType) { - response := &mgmt_pb.GetServiceResponse{} - err := proto.Unmarshal(responseMsg.Body, response) - if err == nil { - out := fmt.Sprintf("\n%10s | %30s | %s\n", "Id", "Endpoint", "Egress") - out += "-----------+--------------------------------+----------\n" - svc := response.Service - out += fmt.Sprintf("%10s | %30s | %s\n", svc.Id, svc.EndpointAddress, svc.Egress) - out += "\n" - fmt.Print(out) - - } else { - out := fmt.Sprintf("Id not found\n") - fmt.Print(out) - } - } else if responseMsg.ContentType == channel2.ContentTypeResultType { - result := channel2.UnmarshalResult(responseMsg) - if result.Success { - fmt.Printf("\nsuccess\n\n") - } else { - fmt.Printf("\nfailure [%s]\n\n", result.Message) + if responseMsg.ContentType == int32(mgmt_pb.ContentType_GetServiceResponseType) { + response := &mgmt_pb.GetServiceResponse{} + err := proto.Unmarshal(responseMsg.Body, response) + if err == nil { + fmt.Printf("\n%10s | %30s\n", "Id", "Terminator Strategy") + fmt.Printf("-----------+--------------------------------+----------\n") + svc := response.Service + fmt.Printf("%10s | %30s\n\n", svc.Id, svc.TerminatorStrategy) + fmt.Printf("Terminators (%v)\n", len(svc.Terminators)) + fmt.Printf("\n%10s | %-12s| %v\n", "Id", "Binding", "Destination") + for _, terminator := range svc.Terminators { + fmt.Printf("%-10s | %-12s | %s\n", terminator.Id, terminator.Binding, + fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) } } else { - panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + fmt.Printf("Id not found\n") } - - case <-time.After(5 * time.Second): - panic(errors.New("timeout")) + } else if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") + } else { + fmt.Printf("\nfailure [%s]\n\n", result.Message) + } + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) } } else { panic(err) diff --git a/ziti-fabric/subcmd/get_terminator.go b/ziti-fabric/subcmd/get_terminator.go new file mode 100644 index 000000000..d25e69168 --- /dev/null +++ b/ziti-fabric/subcmd/get_terminator.go @@ -0,0 +1,77 @@ +/* + Copyright 2020 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package subcmd + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/spf13/cobra" + "time" +) + +func init() { + getTerminatorClient = NewMgmtClient(getTerminator) + getCmd.AddCommand(getTerminator) +} + +var getTerminator = &cobra.Command{ + Use: "terminator ", + Short: "Retrieve a terminator definition", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + if ch, err := getTerminatorClient.Connect(); err == nil { + request := &mgmt_pb.GetTerminatorRequest{ + TerminatorId: args[0], + } + body, err := proto.Marshal(request) + if err != nil { + panic(err) + } + requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_GetTerminatorRequestType), body) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) + if err != nil { + panic(err) + } + if responseMsg.ContentType == int32(mgmt_pb.ContentType_GetTerminatorResponseType) { + response := &mgmt_pb.GetTerminatorResponse{} + err := proto.Unmarshal(responseMsg.Body, response) + if err == nil { + terminator := response.Terminator + fmt.Printf("\n%10s | %-12s| %-12s| %v\n", "Id", "Service", "Binding", "Destination") + fmt.Printf("%-10s | %-12s | %-12s | %v\n", terminator.Id, terminator.ServiceId, terminator.Binding, + fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) + } else { + fmt.Printf("Id not found\n") + } + } else if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") + } else { + fmt.Printf("\nfailure [%s]\n\n", result.Message) + } + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + } + } else { + panic(err) + } + }, +} +var getTerminatorClient *mgmtClient diff --git a/ziti-fabric/subcmd/list_services.go b/ziti-fabric/subcmd/list_services.go index cdebf64cd..d61053661 100644 --- a/ziti-fabric/subcmd/list_services.go +++ b/ziti-fabric/subcmd/list_services.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,11 +17,11 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "github.com/spf13/cobra" "time" ) @@ -42,33 +42,35 @@ var listServices = &cobra.Command{ panic(err) } requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListServicesRequestType), body) - waitCh, err := ch.SendAndWait(requestMsg) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) if err != nil { panic(err) } - select { - case responseMsg := <-waitCh: - if responseMsg.ContentType == int32(mgmt_pb.ContentType_ListServicesResponseType) { - response := &mgmt_pb.ListServicesResponse{} - if err := proto.Unmarshal(responseMsg.Body, response); err == nil { - out := fmt.Sprintf("\nServices: (%d)\n\n", len(response.Services)) - out += fmt.Sprintf("%-12s | %-12s | %s\n", "Id", "Binding", "Destination") - for _, svc := range response.Services { - out += fmt.Sprintf("%-12s | %-12s | %s\n", svc.Id, svc.Binding, fmt.Sprintf("%-12s -> %s", svc.Egress, svc.EndpointAddress)) + if responseMsg.ContentType == int32(mgmt_pb.ContentType_ListServicesResponseType) { + response := &mgmt_pb.ListServicesResponse{} + if err := proto.Unmarshal(responseMsg.Body, response); err == nil { + out := fmt.Sprintf("\nServices: (%d)\n\n", len(response.Services)) + out += fmt.Sprintf("%-12s | %-12s | %s\n", "Id", "Terminator Strategy", "Destination(s)") + for _, svc := range response.Services { + if len(svc.Terminators) > 0 { + out += fmt.Sprintf("%-12s | %-12s | %s\n", svc.Id, svc.TerminatorStrategy, + fmt.Sprintf("%-12s -> %s", svc.Terminators[0].RouterId, svc.Terminators[0].Address)) + for _, terminator := range svc.Terminators[1:] { + out += fmt.Sprintf("%-12s | %-12s | %s\n", "", "", + fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) + } + } else { + out += fmt.Sprintf("%-12s | %-12s | \n", svc.Id, svc.TerminatorStrategy) } - out += "\n" - fmt.Print(out) - } else { - panic(err) } + out += "\n" + fmt.Print(out) } else { - panic(errors.New("unexpected response")) + panic(err) } - - case <-time.After(5 * time.Second): - panic(errors.New("timeout")) + } else { + panic(errors.New("unexpected response")) } - } else { panic(err) } diff --git a/ziti-fabric/subcmd/list_terminators.go b/ziti-fabric/subcmd/list_terminators.go new file mode 100644 index 000000000..f9357177b --- /dev/null +++ b/ziti-fabric/subcmd/list_terminators.go @@ -0,0 +1,71 @@ +/* + Copyright 2020 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package subcmd + +import ( + "errors" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/spf13/cobra" + "time" +) + +func init() { + listTerminatorsClient = NewMgmtClient(listTerminators) + listCmd.AddCommand(listTerminators) +} + +var listTerminators = &cobra.Command{ + Use: "terminators", + Short: "Retrieve terminator definitions", + Run: func(cmd *cobra.Command, args []string) { + if ch, err := listTerminatorsClient.Connect(); err == nil { + request := &mgmt_pb.ListTerminatorsRequest{} + body, err := proto.Marshal(request) + if err != nil { + panic(err) + } + requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListTerminatorsRequestType), body) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) + if err != nil { + panic(err) + } + if responseMsg.ContentType == int32(mgmt_pb.ContentType_ListTerminatorsResponseType) { + response := &mgmt_pb.ListTerminatorsResponse{} + if err := proto.Unmarshal(responseMsg.Body, response); err == nil { + out := fmt.Sprintf("\nTerminators: (%d)\n\n", len(response.Terminators)) + out += fmt.Sprintf("%-12s | %-12s | %-12s | %s\n", "Id", "Service", "Binding", "Destination") + for _, terminator := range response.Terminators { + out += fmt.Sprintf("%-12s | %-12s | %-12s | %s\n", terminator.Id, terminator.ServiceId, terminator.Binding, + fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) + } + out += "\n" + fmt.Print(out) + } else { + panic(err) + } + } else { + panic(errors.New("unexpected response")) + } + } else { + panic(err) + } + }, +} +var listTerminatorsClient *mgmtClient diff --git a/ziti-fabric/subcmd/remove_service.go b/ziti-fabric/subcmd/remove_service.go index 747526834..9572ca954 100644 --- a/ziti-fabric/subcmd/remove_service.go +++ b/ziti-fabric/subcmd/remove_service.go @@ -1,5 +1,5 @@ /* - Copyright 2019 NetFoundry, Inc. + Copyright 2020 NetFoundry, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,11 +17,10 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" - "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" "github.com/spf13/cobra" "time" ) @@ -45,24 +44,19 @@ var removeService = &cobra.Command{ panic(err) } requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_RemoveServiceRequestType), body) - waitCh, err := ch.SendAndWait(requestMsg) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) if err != nil { panic(err) } - select { - case responseMsg := <-waitCh: - if responseMsg.ContentType == channel2.ContentTypeResultType { - result := channel2.UnmarshalResult(responseMsg) - if result.Success { - fmt.Printf("\nsuccess\n\n") - } else { - fmt.Printf("\nfailure [%s]\n\n", result.Message) - } + if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") } else { - panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + fmt.Printf("\nfailure [%s]\n\n", result.Message) } - case <-time.After(5 * time.Second): - panic(errors.New("timeout")) + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) } } }, diff --git a/ziti-fabric/subcmd/remove_terminator.go b/ziti-fabric/subcmd/remove_terminator.go new file mode 100644 index 000000000..a0ae078e7 --- /dev/null +++ b/ziti-fabric/subcmd/remove_terminator.go @@ -0,0 +1,64 @@ +/* + Copyright 2020 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package subcmd + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/spf13/cobra" + "time" +) + +func init() { + removeTerminatorClient = NewMgmtClient(removeTerminator) + removeCmd.AddCommand(removeTerminator) +} + +var removeTerminator = &cobra.Command{ + Use: "terminator ", + Short: "Remove a service terminator from the fabric", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + if ch, err := removeTerminatorClient.Connect(); err == nil { + request := &mgmt_pb.RemoveTerminatorRequest{ + TerminatorId: args[0], + } + body, err := proto.Marshal(request) + if err != nil { + panic(err) + } + requestMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_RemoveTerminatorRequestType), body) + responseMsg, err := ch.SendAndWaitWithTimeout(requestMsg, 5*time.Second) + if err != nil { + panic(err) + } + if responseMsg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(responseMsg) + if result.Success { + fmt.Printf("\nsuccess\n\n") + } else { + fmt.Printf("\nfailure [%s]\n\n", result.Message) + } + } else { + panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) + } + } + }, +} +var removeTerminatorClient *mgmtClient diff --git a/ziti-tunnel/cmd/ziti-tunnel/subcmd/proxy.go b/ziti-tunnel/cmd/ziti-tunnel/subcmd/proxy.go index 51297df7e..c6930d69d 100644 --- a/ziti-tunnel/cmd/ziti-tunnel/subcmd/proxy.go +++ b/ziti-tunnel/cmd/ziti-tunnel/subcmd/proxy.go @@ -17,9 +17,9 @@ package subcmd import ( + "fmt" "github.com/netfoundry/ziti-edge/tunnel/intercept" "github.com/netfoundry/ziti-edge/tunnel/intercept/proxy" - "fmt" "github.com/spf13/cobra" "math" "net" @@ -28,11 +28,12 @@ import ( ) var runProxyCmd = &cobra.Command{ - Use: "proxy [sevice-name:port]", - Short: "Run in 'proxy' mode", - Long: "The 'proxy' intercept mode creates a network listener for each service that is intercepted.", - Args: cobra.MinimumNArgs(1), - RunE: runProxy, + Use: "proxy [sevice-name:port]", + Short: "Run in 'proxy' mode", + Long: "The 'proxy' intercept mode creates a network listener for each service that is intercepted.", + Args: cobra.MinimumNArgs(1), + RunE: runProxy, + PostRun: rootPostRun, } func init() { diff --git a/ziti-tunnel/cmd/ziti-tunnel/subcmd/root.go b/ziti-tunnel/cmd/ziti-tunnel/subcmd/root.go index 18044b1cd..9d6f24a59 100644 --- a/ziti-tunnel/cmd/ziti-tunnel/subcmd/root.go +++ b/ziti-tunnel/cmd/ziti-tunnel/subcmd/root.go @@ -45,10 +45,9 @@ func init() { } var root = &cobra.Command{ - Use: filepath.Base(os.Args[0]), - Short: "Ziti Tunnel", - PersistentPreRun: rootPreRun, - PersistentPostRun: rootPostRun, + Use: filepath.Base(os.Args[0]), + Short: "Ziti Tunnel", + PersistentPreRun: rootPreRun, } var interceptor intercept.Interceptor diff --git a/ziti-tunnel/cmd/ziti-tunnel/subcmd/tproxy.go b/ziti-tunnel/cmd/ziti-tunnel/subcmd/tproxy.go index 3475443ad..a83aaf2f0 100644 --- a/ziti-tunnel/cmd/ziti-tunnel/subcmd/tproxy.go +++ b/ziti-tunnel/cmd/ziti-tunnel/subcmd/tproxy.go @@ -19,16 +19,17 @@ package subcmd import ( - "github.com/netfoundry/ziti-edge/tunnel/intercept/tproxy" "fmt" + "github.com/netfoundry/ziti-edge/tunnel/intercept/tproxy" "github.com/spf13/cobra" ) var runTProxyCmd = &cobra.Command{ - Use: "tproxy", - Short: "Use the 'tproxy' interceptor", - Long: "The 'tproxy' interceptor captures packets by using the TPROXY iptables target.", - RunE: runTProxy, + Use: "tproxy", + Short: "Use the 'tproxy' interceptor", + Long: "The 'tproxy' interceptor captures packets by using the TPROXY iptables target.", + RunE: runTProxy, + PostRun: rootPostRun, } func init() { diff --git a/ziti-tunnel/cmd/ziti-tunnel/subcmd/tun.go b/ziti-tunnel/cmd/ziti-tunnel/subcmd/tun.go index 6b97ec440..6305bc989 100644 --- a/ziti-tunnel/cmd/ziti-tunnel/subcmd/tun.go +++ b/ziti-tunnel/cmd/ziti-tunnel/subcmd/tun.go @@ -19,9 +19,9 @@ package subcmd import ( - "github.com/netfoundry/ziti-edge/tunnel/intercept/tun" "fmt" "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-edge/tunnel/intercept/tun" "github.com/spf13/cobra" ) @@ -36,10 +36,11 @@ func init() { } var tunCmd = &cobra.Command{ - Use: "tun ", - Short: "Intercept packets with tun interface", - Args: cobra.NoArgs, - RunE: runTun, + Use: "tun ", + Short: "Intercept packets with tun interface", + Args: cobra.NoArgs, + RunE: runTun, + PostRun: rootPostRun, } func runTun(cmd *cobra.Command, args []string) error { diff --git a/ziti/cmd/ziti/cmd/edge_controller/create.go b/ziti/cmd/ziti/cmd/edge_controller/create.go index 606f22263..350e8283b 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/create.go +++ b/ziti/cmd/ziti/cmd/edge_controller/create.go @@ -43,6 +43,7 @@ func newCreateCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com cmd.AddCommand(newCreateConfigCmd(f, out, errOut)) cmd.AddCommand(newCreateEdgeRouterCmd(f, out, errOut)) cmd.AddCommand(newCreateEdgeRouterPolicyCmd(f, out, errOut)) + cmd.AddCommand(newCreateTerminatorCmd(f, out, errOut)) cmd.AddCommand(newCreateIdentityCmd(f, out, errOut)) cmd.AddCommand(newCreateServiceCmd(f, out, errOut)) cmd.AddCommand(newCreateServiceEdgeRouterPolicyCmd(f, out, errOut)) diff --git a/ziti/cmd/ziti/cmd/edge_controller/create_service.go b/ziti/cmd/ziti/cmd/edge_controller/create_service.go index 5c2127608..5de48f466 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/create_service.go +++ b/ziti/cmd/ziti/cmd/edge_controller/create_service.go @@ -22,17 +22,16 @@ import ( "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/common" cmdutil "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/factory" cmdhelper "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/helpers" - "github.com/pkg/errors" "github.com/spf13/cobra" "io" ) type createServiceOptions struct { commonOptions - hostedService bool - tags map[string]string - roleAttributes []string - configs []string + terminatorStrategy string + tags map[string]string + roleAttributes []string + configs []string } // newCreateServiceCmd creates the 'edge controller create service local' command for the given entity type @@ -49,7 +48,7 @@ func newCreateServiceCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *co } cmd := &cobra.Command{ - Use: "service [egress node]? [egress endpoint uri]?", + Use: "service ", Short: "creates a service managed by the Ziti Edge Controller", Long: "creates a service managed by the Ziti Edge Controller", Args: cobra.MinimumNArgs(1), @@ -66,31 +65,22 @@ func newCreateServiceCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *co cmd.Flags().SetInterspersed(true) cmd.Flags().StringToStringVarP(&options.tags, "tags", "t", nil, "Add tags to service definition") cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") - cmd.Flags().BoolVar(&options.hostedService, "hosted", false, "Indicates that this is a hosted service") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new service") cmd.Flags().StringSliceVarP(&options.configs, "configs", "c", nil, "Configuration id or names to be associated with the new service") + cmd.Flags().StringVar(&options.terminatorStrategy, "terminator-strategy", "", "Specifies the terminator strategy for the service") return cmd } -// runCreateNativeService implements the command to create a service +// runCreateService implements the command to create a service func runCreateService(o *createServiceOptions) (err error) { entityData := gabs.New() setJSONValue(entityData, o.Args[0], "name") + if o.terminatorStrategy != "" { + setJSONValue(entityData, o.terminatorStrategy, "terminatorStrategy") + } setJSONValue(entityData, o.roleAttributes, "roleAttributes") setJSONValue(entityData, o.configs, "configs") - - if o.hostedService || len(o.Args) == 1 { - setJSONValue(entityData, "unclaimed", "egressRouter") - setJSONValue(entityData, "hosted:unclaimed", "endpointAddress") - } else { - if len(o.Args) < 3 { - return errors.Errorf("if --hosted is not set, you must provide egress router and endpoint address") - } - setJSONValue(entityData, o.Args[1], "egressRouter") - setJSONValue(entityData, o.Args[2], "endpointAddress") - } - setJSONValue(entityData, o.tags, "tags") result, err := createEntityOfType("services", entityData.String(), &o.commonOptions) diff --git a/ziti/cmd/ziti/cmd/edge_controller/create_terminator.go b/ziti/cmd/ziti/cmd/edge_controller/create_terminator.go new file mode 100644 index 000000000..0fbf6e0e0 --- /dev/null +++ b/ziti/cmd/ziti/cmd/edge_controller/create_terminator.go @@ -0,0 +1,103 @@ +/* + Copyright 2020 NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package edge_controller + +import ( + "fmt" + "github.com/Jeffail/gabs" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/common" + cmdutil "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/factory" + cmdhelper "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/helpers" + "github.com/spf13/cobra" + "io" +) + +type createTerminatorOptions struct { + commonOptions + binding string + tags map[string]string +} + +// newCreateTerminatorCmd creates the 'edge controller create Terminator local' command for the given entity type +func newCreateTerminatorCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { + options := &createTerminatorOptions{ + commonOptions: commonOptions{ + CommonOptions: common.CommonOptions{ + Factory: f, + Out: out, + Err: errOut, + }, + }, + tags: make(map[string]string), + } + + cmd := &cobra.Command{ + Use: "terminator service router address", + Short: "creates an terminator managed by the Ziti Edge Controller", + Long: "creates an terminator managed by the Ziti Edge Controller", + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runCreateTerminator(options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + cmd.Flags().StringToStringVarP(&options.tags, "tags", "t", nil, "Add tags to terminator definition") + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + cmd.Flags().StringVar(&options.binding, "binding", "transport", "Add tags to terminator definition") + + return cmd +} + +// runCreateTerminator implements the command to create a Terminator +func runCreateTerminator(o *createTerminatorOptions) (err error) { + entityData := gabs.New() + service, err := mapNameToID("services", o.Args[0]) + if err != nil { + return err + } + + router, err := mapNameToID("edge-routers", o.Args[1]) + if err != nil { + router = o.Args[1] // might be a pure fabric router, id might not be UUID + } + + setJSONValue(entityData, service, "service") + setJSONValue(entityData, router, "router") + setJSONValue(entityData, o.binding, "binding") + setJSONValue(entityData, o.Args[2], "address") + setJSONValue(entityData, o.tags, "tags") + + result, err := createEntityOfType("terminators", entityData.String(), &o.commonOptions) + + if err != nil { + panic(err) + } + + TerminatorId := result.S("data", "id").Data() + + if _, err = fmt.Fprintf(o.Out, "%v\n", TerminatorId); err != nil { + panic(err) + } + + return err +} diff --git a/ziti/cmd/ziti/cmd/edge_controller/delete.go b/ziti/cmd/ziti/cmd/edge_controller/delete.go index 64647a1c1..6323dbffe 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/delete.go +++ b/ziti/cmd/ziti/cmd/edge_controller/delete.go @@ -51,6 +51,7 @@ func newDeleteCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com } 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("edge-router", runDeleteEntityOfType, newOptions())) @@ -60,7 +61,7 @@ func newDeleteCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com cmd.AddCommand(newDeleteCmdForEntityType("service-edge-router-policy", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("service-policy", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("session", runDeleteEntityOfType, newOptions())) - cmd.AddCommand(newDeleteAuthenticatorCmd("authenticator", newOptions())) + cmd.AddCommand(newDeleteCmdForEntityType("terminator", runDeleteEntityOfType, newOptions())) return cmd } diff --git a/ziti/cmd/ziti/cmd/edge_controller/list.go b/ziti/cmd/ziti/cmd/edge_controller/list.go index 4fbceb34c..f74f8f833 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/list.go +++ b/ziti/cmd/ziti/cmd/edge_controller/list.go @@ -58,6 +58,7 @@ func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma cmd.AddCommand(newListCmdForEntityType("configs", runListConfigs, newOptions())) cmd.AddCommand(newListCmdForEntityType("edge-routers", runListEdgeRouters, newOptions())) cmd.AddCommand(newListCmdForEntityType("edge-router-policies", runListEdgeRouterPolicies, newOptions())) + cmd.AddCommand(newListCmdForEntityType("terminators", runListTerminators, newOptions())) cmd.AddCommand(newListCmdForEntityType("gateways", runListEdgeRouters, newOptions())) cmd.AddCommand(newListCmdForEntityType("identities", runListIdentities, newOptions())) cmd.AddCommand(newListServicesCmd(newOptions())) @@ -83,6 +84,8 @@ func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma serviceListRootCmd := newEntityListRootCmd("service") serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "configs", outputConfigs, newOptions())) serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "service-policies", outputServicePolicies, newOptions())) + serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "service-edge-router-policies", outputServiceEdgeRouterPolicies, newOptions())) + serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "terminators", outputTerminators, newOptions())) serviceEdgeRouterPolicyListRootCmd := newEntityListRootCmd("service-edge-router-policy") serviceEdgeRouterPolicyListRootCmd.AddCommand(newSubListCmdForEntityType("service-edge-router-policies", "services", outputServices, newOptions())) @@ -174,7 +177,7 @@ func newSubListCmdForEntityType(entityType string, subType string, outputF outpu Use: fmt.Sprintf("%v ", subType), Short: desc, Long: desc, - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { options.Cmd = cmd options.Args = args @@ -281,6 +284,34 @@ func outputEdgeRouterPolicies(o *commonOptions, children []*gabs.Container) erro return nil } +func runListTerminators(o *commonOptions) error { + children, err := listEntitiesWithOptions("terminators", o) + if err != nil { + return err + } + return outputTerminators(o, children) +} + +func outputTerminators(o *commonOptions, children []*gabs.Container) error { + if o.OutputJSONResponse { + return nil + } + + for _, entity := range children { + id, _ := entity.Path("id").Data().(string) + serviceId := entity.Path("serviceId").Data().(string) + routerId := entity.Path("routerId").Data().(string) + binding := entity.Path("binding").Data().(string) + address := entity.Path("address").Data().(string) + _, err := fmt.Fprintf(o.Out, "id: %v serviceId: %v routerId: %v binding: %v address: %v\n", + id, serviceId, routerId, binding, address) + if err != nil { + return err + } + } + return nil +} + func runListServices(asIdentity string, configTypes string, options *commonOptions) error { params := url.Values{} if len(options.Args) > 0 { @@ -307,8 +338,9 @@ func outputServices(o *commonOptions, children []*gabs.Container) error { for _, entity := range children { id, _ := entity.Path("id").Data().(string) name, _ := entity.Path("name").Data().(string) - edgeRouterRoles := entity.Path("edgeRouterRoles").String() - _, err := fmt.Fprintf(o.Out, "id: %v name: %v edge router roles: %v\n", id, name, edgeRouterRoles) + terminatorStrategy, _ := entity.Path("terminatorStrategy").Data().(string) + roleAttributes := entity.Path("roleAttributes").String() + _, err := fmt.Fprintf(o.Out, "id: %v name: %v terminator strategy: %v role attributes: %v\n", id, name, terminatorStrategy, roleAttributes) if err != nil { return err } @@ -509,8 +541,8 @@ func runListSessions(o *commonOptions) error { id, _ := entity.Path("id").Data().(string) sessionId, _ := entity.Path("apiSession.id").Data().(string) serviceName, _ := entity.Path("service.name").Data().(string) - hosting, _ := entity.Path("hosting").Data().(bool) - if _, err := fmt.Fprintf(o.Out, "id: %v sessionId: %v serviceName: %v hosting: %v\n", id, sessionId, serviceName, hosting); err != nil { + sessionType, _ := entity.Path("type").Data().(string) + if _, err := fmt.Fprintf(o.Out, "id: %v sessionId: %v serviceName: %v type: %v\n", id, sessionId, serviceName, sessionType); err != nil { return err } } @@ -520,12 +552,17 @@ func runListSessions(o *commonOptions) error { func runListChilden(parentType, childType string, o *commonOptions, outputF outputFunction) error { idOrName := o.Args[0] - serviceId, err := mapNameToID(parentType, idOrName) + parentId, err := mapNameToID(parentType, idOrName) if err != nil { return err } - children, err := filterSubEntitiesOfType(parentType, childType, serviceId, "", o) + filter := "" + if len(o.Args) > 1 { + filter = o.Args[1] + } + + children, err := filterSubEntitiesOfType(parentType, childType, parentId, filter, o) if err != nil { return err } diff --git a/ziti/cmd/ziti/cmd/version.go b/ziti/cmd/ziti/cmd/version.go index 0d5f850df..7243482b5 100644 --- a/ziti/cmd/ziti/cmd/version.go +++ b/ziti/cmd/ziti/cmd/version.go @@ -17,18 +17,18 @@ package cmd import ( - "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/table" - "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/internal/log" "fmt" "github.com/blang/semver" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/table" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/internal/log" "io" // "strings" + "github.com/netfoundry/ziti-cmd/common/version" cmdutil "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/factory" cmdhelper "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/helpers" c "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/constants" "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/util" - "github.com/netfoundry/ziti-cmd/common/version" "github.com/spf13/cobra" ) @@ -182,7 +182,7 @@ func (o *VersionOptions) versionCheckZitiApp(zitiApp string) error { if err != nil { log.Warnf("\nAn err occurred: %s", err) } else { - currentVersion, err = semver.Make(output) + currentVersion, err = semver.ParseTolerant(output) if err != nil { log.Warnf("Failed to get %s version: %s\n", zitiApp, err) return err