diff --git a/CHANGELOG.md b/CHANGELOG.md index cacd75e3d..e3f665233 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# Release 0.16.2 + +* What's New + * Smart routing fixes + * [Persist Terminator Precedence](https://github.com/openziti/fabric/issues/112) + * [Terminators and Fixed Link Cost, Incorrect Path Selection](https://github.com/openziti/fabric/issues/121) + * [If link vanishes during reroute, controller can panic](https://github.com/openziti/fabric/issues/122) + * [Scale latency metric when used for path costing](https://github.com/openziti/fabric/issues/123) + * [Services not always getting cleared from cache when terminators are updated](https://github.com/openziti/fabric/issues/124) + * [Fix service policy denormalization migration](https://github.com/openziti/edge/issues/291) + # Release 0.16.1 * What's New diff --git a/etc/tmpl/edge.router.yml b/etc/tmpl/edge.router.yml new file mode 100644 index 000000000..e44b5e589 --- /dev/null +++ b/etc/tmpl/edge.router.yml @@ -0,0 +1,90 @@ +v: 3 + +# (required) The certificates, ca chains, and private key used to represent this routers identity +# +# If the 'edge" section is enabled and enrollment is run, the files in this section will be written to with the results. +# The "key" value can be provided through any of the support private key engines (file, etc.). +# +# If the 'key' value is a file and that file exists; it is expected to a pre-generated private key. It will be used for +# the enrollment process and it will back the certificates generated during enrollment. If the file does not exist, it +# will be generated. +# +# The 'cert', 'server_cert', and 'ca' files will be overwritten with the results of the enrollment process. +# +# When running the ziti-router the files/values in this section will be read and used. The 'cert' value will be used +# as the client certificate to connect to the controller. The 'server_cert' is used for all servers/listeners. The +# 'ca' value is used to populate an internally Trusted CA pool. +identity: + cert: ${ZITI_DATA}/edge-router-client.cert.pem + server_cert: ${ZITI_DATA}/edge-router-server.cert.pem + key: ${ZITI_DATA}/edge-router.key.pem + ca: ${ZITI_DATA}/edge-router-ca-chain.cert.pem + +#trace: +# path: 001.trace + +#profile: +# memory: +# path: 001.memprof +# cpu: +# path: 001.cpuprof + +ctrl: + endpoint: tls:${CONTROLLER_HOST}:${CONTROLLER_PORT} + +link: + dialers: + - binding: transport + listeners: + - binding: transport + bind: tls:127.0.0.1:${LINK_LISTENER_PORT} + advertise: tls:127.0.0.1:${LINK_LISTENER_PORT} + + +# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (optional) Determines the rate at which API session heartbeats are sent for connected SDK clients (default: 60) + heartbeatIntervalSeconds: 60 + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + dns: + - "localhost" + - "test-network" + - "test-network.localhost" + - "ziti-dev-ingress01" + email: + - "admin@example.com" + ip: + - "127.0.0.1" + uri: + - "ziti://ziti-dev-gateway01/made/up/example" + +dialers: + - binding: udp + - binding: transport + +listeners: + - binding: edge + address: tls:0.0.0.0:${ZITI_EDGE_PORT} + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: 127.0.0.1:${ZITI_EDGE_PORT} + # (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 diff --git a/go.mod b/go.mod index 017974dfd..066853125 100644 --- a/go.mod +++ b/go.mod @@ -26,10 +26,10 @@ 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/openziti/edge v0.16.4 - github.com/openziti/fabric v0.12.5 - github.com/openziti/foundation v0.13.2 - github.com/openziti/sdk-golang v0.13.36 + github.com/openziti/edge v0.16.9 + github.com/openziti/fabric v0.13.1 + github.com/openziti/foundation v0.14.0 + github.com/openziti/sdk-golang v0.13.39 github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 diff --git a/go.sum b/go.sum index dc636d028..94d6ee780 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/runtime v0.19.15 h1:2GIefxs9Rx1vCDNghRtypRq+ig8KSLrjHbAYI/gCLCM= github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= -github.com/go-openapi/runtime v0.19.20 h1:J/t+QIjbcoq8WJvjGxRKiFBhqUE8slS9SbmD0Oi/raQ= -github.com/go-openapi/runtime v0.19.20/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= +github.com/go-openapi/runtime v0.19.21 h1:81PiYus9l6fwwS4EwhJD+tQb3EPZBeWfgdAVTfFD25Q= +github.com/go-openapi/runtime v0.19.21/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= @@ -233,8 +233,8 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -242,6 +242,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -406,14 +408,14 @@ github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/openziti/edge v0.16.4 h1:NTcTeum1pu1jYiYyKvosw1CHnruePV65tTLPBosWXhQ= -github.com/openziti/edge v0.16.4/go.mod h1:RHlF/l+PtXQHDslOaY0oX6vUrAqGQ9hV1qCgSHhJAlc= -github.com/openziti/fabric v0.12.5 h1:K85PendocjszlkLnFC3dGtqqBlYnA9hJdi9WdSmlLig= -github.com/openziti/fabric v0.12.5/go.mod h1:ylhCe7OOkpJGFwy+SYtZn2VTk0q1YVtGZO8yDjCUVLY= -github.com/openziti/foundation v0.13.2 h1:oLyq+JQzUiVoodklMb4T2gd/knZznxAvYIOmVx8g8N0= -github.com/openziti/foundation v0.13.2/go.mod h1:EZ17GjcO0gq8VfVHZeKjkWj+h/mgYUrWhjpA4+XEN6w= -github.com/openziti/sdk-golang v0.13.36 h1:UNo9jYZu0pj6UK8OmjXIzv7bbCOpX/SCyN701/SbItA= -github.com/openziti/sdk-golang v0.13.36/go.mod h1:nUBh+1zeaTqhmk8JwPXptsl/6uaQLRsfvOKEILg2jLY= +github.com/openziti/edge v0.16.9 h1:olBPM0UrGV3kT8lR+YmOi743n0UWKvX7Fb8h4q3aa1E= +github.com/openziti/edge v0.16.9/go.mod h1:yl/j3KlVtIGZfakpnaWS+D229cb2E9acgdSUg/fEzm8= +github.com/openziti/fabric v0.13.1 h1:ukHkSveM1XxoIqVCE0uCKUWilZibftM0MuZ0572kz0M= +github.com/openziti/fabric v0.13.1/go.mod h1:5XwSupcpP8mLRVz8vgjoTDD4V8t/TpvMfIZKmT3COLY= +github.com/openziti/foundation v0.14.0 h1:a4Wu/zpxJ8fuWuO+LPfTyroURWymtz81KWYmSyuhbJM= +github.com/openziti/foundation v0.14.0/go.mod h1:N6QMLsB1vXnTa8SMWXRpyMOpP5af8Nd2MxeBJEiF+hk= +github.com/openziti/sdk-golang v0.13.39 h1:g+smQkfuB/akY/Uz94Aju37azMI/JOt73Mx6nJzovws= +github.com/openziti/sdk-golang v0.13.39/go.mod h1:1fpsjitE5ue8EVGFXhjCMq2E9+FxacopAAlEQ/RlEHw= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= diff --git a/ziti-fabric/subcmd/create_terminator.go b/ziti-fabric/subcmd/create_terminator.go index 2f47d3817..560a45165 100644 --- a/ziti-fabric/subcmd/create_terminator.go +++ b/ziti-fabric/subcmd/create_terminator.go @@ -21,15 +21,21 @@ import ( "github.com/golang/protobuf/proto" "github.com/openziti/fabric/pb/mgmt_pb" "github.com/openziti/foundation/channel2" + "github.com/openziti/foundation/util/stringz" "github.com/spf13/cobra" "time" ) var createTerminatorClient *mgmtClient var createTerminatorBinding string +var createTerminatorCost uint32 +var createTerminatorPrecedence string func init() { createTerminator.Flags().StringVar(&createTerminatorBinding, "binding", "transport", "Terminator binding") + createTerminator.Flags().Uint32VarP(&createTerminatorCost, "cost", "c", 0, "Set the terminator cost") + createTerminator.Flags().StringVarP(&createTerminatorPrecedence, "precedence", "p", "default", "Set the terminator precedence ('default', 'required' or 'failed')") + createTerminatorClient = NewMgmtClient(createTerminator) createCmd.AddCommand(createTerminator) } @@ -39,13 +45,30 @@ var createTerminator = &cobra.Command{ Short: "Create a new fabric service terminator", Args: cobra.ExactArgs(3), Run: func(cmd *cobra.Command, args []string) { + validValues := []string{"default", "required", "failed"} + if !stringz.Contains(validValues, createTerminatorPrecedence) { + if _, err := fmt.Fprintf(cmd.OutOrStdout(), "Invalid precedence %v. Must be one of %+v\n", createTerminatorPrecedence, validValues); err != nil { + panic(err) + } + return + } + + precedence := mgmt_pb.TerminatorPrecedence_Default + if createTerminatorPrecedence == "required" { + precedence = mgmt_pb.TerminatorPrecedence_Required + } else if createTerminatorPrecedence == "failed" { + precedence = mgmt_pb.TerminatorPrecedence_Failed + } + 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], + ServiceId: args[0], + RouterId: args[1], + Binding: createTerminatorBinding, + Address: args[2], + Precedence: precedence, + Cost: createTerminatorCost, }, } body, err := proto.Marshal(request) diff --git a/ziti-fabric/subcmd/get_terminator.go b/ziti-fabric/subcmd/get_terminator.go index c14241061..0dc33a22f 100644 --- a/ziti-fabric/subcmd/get_terminator.go +++ b/ziti-fabric/subcmd/get_terminator.go @@ -53,9 +53,9 @@ var getTerminator = &cobra.Command{ 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)) + fmt.Printf("\n%10s | %-12s| %-16s| %-12v| %-12v| %v\n", "Id", "Service", "Binding", "Precedence", "Static Cost", "Destination") + fmt.Printf("%-10s | %-12s | %-16s | %-12v| %-12v| %v\n", terminator.Id, terminator.ServiceId, terminator.Binding, + terminator.Precedence.String(), terminator.Cost, fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) } else { fmt.Printf("Id not found\n") } diff --git a/ziti-fabric/subcmd/list_links.go b/ziti-fabric/subcmd/list_links.go index 8ae2a38c6..a4c0b1b9c 100644 --- a/ziti-fabric/subcmd/list_links.go +++ b/ziti-fabric/subcmd/list_links.go @@ -17,11 +17,11 @@ package subcmd import ( - "github.com/openziti/foundation/channel2" - "github.com/openziti/fabric/pb/mgmt_pb" "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/openziti/fabric/pb/mgmt_pb" + "github.com/openziti/foundation/channel2" "github.com/spf13/cobra" "sort" "time" @@ -58,7 +58,7 @@ func listLinks(cmd *cobra.Command, args []string) { err := proto.Unmarshal(responseMsg.Body, response) if err == nil { out := fmt.Sprintf("\nLinks: (%d)\n\n", len(response.Links)) - out += fmt.Sprintf("%-6s | %-24s -> %-24s | %-12s | %-4s | %-12s\n", "Id", "Src", "Dst", "State", "Cost", "Latency") + out += fmt.Sprintf("%-6s | %-24s -> %-24s | %-12s | %-4s | %-13s | %-12s | %-6s\n", "Id", "Src", "Dst", "State", "Cost", "Latency", "Full Cost", "Status") sort.Slice(response.Links, func(i, j int) bool { if response.Links[i].Src == response.Links[j].Src { return response.Links[i].Dst < response.Links[j].Dst @@ -66,14 +66,16 @@ func listLinks(cmd *cobra.Command, args []string) { return response.Links[i].Src < response.Links[j].Src }) for _, l := range response.Links { - down := "" + status := "up" if l.Down { - down = "->down<-" + status = "down" } // Convert nanoseconds to fractional seconds - srcLatency := float64(l.SrcLatency) / 1000000000.0 - dstLatency := float64(l.DstLatency) / 1000000000.0 - out += fmt.Sprintf("%-6s | %-24s -> %-24s | %-12s | %-4d | %-0.4f %-0.4f %s\n", l.Id, l.Src, l.Dst, l.State, l.Cost, srcLatency, dstLatency, down) + srcLatency := float64(l.SrcLatency) / 1_000_000_000.0 + dstLatency := float64(l.DstLatency) / 1_000_000_000.0 + cost := (l.SrcLatency / 1_000_000) + (l.DstLatency / 1_000_000) + int64(l.Cost) + out += fmt.Sprintf("%-6s | %-24s -> %-24s | %-12s | %-4d | %-0.4f %-0.4f | %-12v | %-6v\n", l.Id, l.Src, l.Dst, l.State, l.Cost, srcLatency, dstLatency, + cost, status) } out += "\n" fmt.Print(out) diff --git a/ziti-fabric/subcmd/list_terminators.go b/ziti-fabric/subcmd/list_terminators.go index 9b65f0146..beff4cb48 100644 --- a/ziti-fabric/subcmd/list_terminators.go +++ b/ziti-fabric/subcmd/list_terminators.go @@ -56,10 +56,10 @@ var listTerminators = &cobra.Command{ 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") + out += fmt.Sprintf("%-10s | %-12s | %-16s | %-12s | %-12s | %s\n", "Id", "Service", "Binding", "Static Cost", "Precedence", "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 += fmt.Sprintf("%-10v | %-12v | %-16v | %-12v | %-12v | %s\n", terminator.Id, terminator.ServiceId, terminator.Binding, + terminator.Cost, terminator.Precedence, fmt.Sprintf("%-12s -> %s", terminator.RouterId, terminator.Address)) } out += "\n" fmt.Print(out)