khenaidoo | ffe076b | 2019-01-15 16:08:08 -0500 | [diff] [blame^] | 1 | // Copyright 2016 The etcd Authors |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package etcdmain |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "net" |
| 20 | "net/url" |
| 21 | "os" |
| 22 | "time" |
| 23 | |
| 24 | "github.com/coreos/etcd/proxy/tcpproxy" |
| 25 | |
| 26 | "github.com/spf13/cobra" |
| 27 | ) |
| 28 | |
| 29 | var ( |
| 30 | gatewayListenAddr string |
| 31 | gatewayEndpoints []string |
| 32 | gatewayDNSCluster string |
| 33 | gatewayInsecureDiscovery bool |
| 34 | getewayRetryDelay time.Duration |
| 35 | gatewayCA string |
| 36 | ) |
| 37 | |
| 38 | var ( |
| 39 | rootCmd = &cobra.Command{ |
| 40 | Use: "etcd", |
| 41 | Short: "etcd server", |
| 42 | SuggestFor: []string{"etcd"}, |
| 43 | } |
| 44 | ) |
| 45 | |
| 46 | func init() { |
| 47 | rootCmd.AddCommand(newGatewayCommand()) |
| 48 | } |
| 49 | |
| 50 | // newGatewayCommand returns the cobra command for "gateway". |
| 51 | func newGatewayCommand() *cobra.Command { |
| 52 | lpc := &cobra.Command{ |
| 53 | Use: "gateway <subcommand>", |
| 54 | Short: "gateway related command", |
| 55 | } |
| 56 | lpc.AddCommand(newGatewayStartCommand()) |
| 57 | |
| 58 | return lpc |
| 59 | } |
| 60 | |
| 61 | func newGatewayStartCommand() *cobra.Command { |
| 62 | cmd := cobra.Command{ |
| 63 | Use: "start", |
| 64 | Short: "start the gateway", |
| 65 | Run: startGateway, |
| 66 | } |
| 67 | |
| 68 | cmd.Flags().StringVar(&gatewayListenAddr, "listen-addr", "127.0.0.1:23790", "listen address") |
| 69 | cmd.Flags().StringVar(&gatewayDNSCluster, "discovery-srv", "", "DNS domain used to bootstrap initial cluster") |
| 70 | cmd.Flags().BoolVar(&gatewayInsecureDiscovery, "insecure-discovery", false, "accept insecure SRV records") |
| 71 | cmd.Flags().StringVar(&gatewayCA, "trusted-ca-file", "", "path to the client server TLS CA file.") |
| 72 | |
| 73 | cmd.Flags().StringSliceVar(&gatewayEndpoints, "endpoints", []string{"127.0.0.1:2379"}, "comma separated etcd cluster endpoints") |
| 74 | |
| 75 | cmd.Flags().DurationVar(&getewayRetryDelay, "retry-delay", time.Minute, "duration of delay before retrying failed endpoints") |
| 76 | |
| 77 | return &cmd |
| 78 | } |
| 79 | |
| 80 | func stripSchema(eps []string) []string { |
| 81 | var endpoints []string |
| 82 | |
| 83 | for _, ep := range eps { |
| 84 | |
| 85 | if u, err := url.Parse(ep); err == nil && u.Host != "" { |
| 86 | ep = u.Host |
| 87 | } |
| 88 | |
| 89 | endpoints = append(endpoints, ep) |
| 90 | } |
| 91 | |
| 92 | return endpoints |
| 93 | } |
| 94 | |
| 95 | func startGateway(cmd *cobra.Command, args []string) { |
| 96 | srvs := discoverEndpoints(gatewayDNSCluster, gatewayCA, gatewayInsecureDiscovery) |
| 97 | if len(srvs.Endpoints) == 0 { |
| 98 | // no endpoints discovered, fall back to provided endpoints |
| 99 | srvs.Endpoints = gatewayEndpoints |
| 100 | } |
| 101 | // Strip the schema from the endpoints because we start just a TCP proxy |
| 102 | srvs.Endpoints = stripSchema(srvs.Endpoints) |
| 103 | if len(srvs.SRVs) == 0 { |
| 104 | for _, ep := range srvs.Endpoints { |
| 105 | h, p, err := net.SplitHostPort(ep) |
| 106 | if err != nil { |
| 107 | plog.Fatalf("error parsing endpoint %q", ep) |
| 108 | } |
| 109 | var port uint16 |
| 110 | fmt.Sscanf(p, "%d", &port) |
| 111 | srvs.SRVs = append(srvs.SRVs, &net.SRV{Target: h, Port: port}) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | if len(srvs.Endpoints) == 0 { |
| 116 | plog.Fatalf("no endpoints found") |
| 117 | } |
| 118 | |
| 119 | l, err := net.Listen("tcp", gatewayListenAddr) |
| 120 | if err != nil { |
| 121 | fmt.Fprintln(os.Stderr, err) |
| 122 | os.Exit(1) |
| 123 | } |
| 124 | |
| 125 | tp := tcpproxy.TCPProxy{ |
| 126 | Listener: l, |
| 127 | Endpoints: srvs.SRVs, |
| 128 | MonitorInterval: getewayRetryDelay, |
| 129 | } |
| 130 | |
| 131 | // At this point, etcd gateway listener is initialized |
| 132 | notifySystemd() |
| 133 | |
| 134 | tp.Run() |
| 135 | } |