blob: 5487414ebd58bfc2ea6ac0efa5fdf515b7b09612 [file] [log] [blame]
khenaidooffe076b2019-01-15 16:08:08 -05001// 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
15package etcdmain
16
17import (
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
29var (
30 gatewayListenAddr string
31 gatewayEndpoints []string
32 gatewayDNSCluster string
33 gatewayInsecureDiscovery bool
34 getewayRetryDelay time.Duration
35 gatewayCA string
36)
37
38var (
39 rootCmd = &cobra.Command{
40 Use: "etcd",
41 Short: "etcd server",
42 SuggestFor: []string{"etcd"},
43 }
44)
45
46func init() {
47 rootCmd.AddCommand(newGatewayCommand())
48}
49
50// newGatewayCommand returns the cobra command for "gateway".
51func 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
61func 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
80func 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
95func 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}