github.com/uber/kraken@v0.1.4/tracker/cmd/cmd.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 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 package cmd 15 16 import ( 17 "flag" 18 19 "github.com/uber/kraken/lib/healthcheck" 20 "github.com/uber/kraken/lib/upstream" 21 "github.com/uber/kraken/metrics" 22 "github.com/uber/kraken/nginx" 23 "github.com/uber/kraken/origin/blobclient" 24 "github.com/uber/kraken/tracker/originstore" 25 "github.com/uber/kraken/tracker/peerhandoutpolicy" 26 "github.com/uber/kraken/tracker/peerstore" 27 "github.com/uber/kraken/tracker/trackerserver" 28 "github.com/uber/kraken/utils/configutil" 29 "github.com/uber/kraken/utils/log" 30 31 "github.com/andres-erbsen/clock" 32 "github.com/uber-go/tally" 33 "go.uber.org/zap" 34 ) 35 36 // Flags define tracker CLI flags. 37 type Flags struct { 38 Port int 39 ConfigFile string 40 KrakenCluster string 41 SecretsFile string 42 } 43 44 // ParseFlags parses tracker CLI flags. 45 func ParseFlags() *Flags { 46 var flags Flags 47 flag.IntVar( 48 &flags.Port, "port", 0, "port to listen on") 49 flag.StringVar( 50 &flags.ConfigFile, "config", "", "configuration file path") 51 flag.StringVar( 52 &flags.KrakenCluster, "cluster", "", "cluster name (e.g. prod01-zone1)") 53 flag.StringVar( 54 &flags.SecretsFile, "secrets", "", "path to a secrets YAML file to load into configuration") 55 flag.Parse() 56 return &flags 57 } 58 59 type options struct { 60 config *Config 61 metrics tally.Scope 62 logger *zap.Logger 63 } 64 65 // Option defines an optional Run parameter. 66 type Option func(*options) 67 68 // WithConfig ignores config/secrets flags and directly uses the provided config 69 // struct. 70 func WithConfig(c Config) Option { 71 return func(o *options) { o.config = &c } 72 } 73 74 // WithMetrics ignores metrics config and directly uses the provided tally scope. 75 func WithMetrics(s tally.Scope) Option { 76 return func(o *options) { o.metrics = s } 77 } 78 79 // WithLogger ignores logging config and directly uses the provided logger. 80 func WithLogger(l *zap.Logger) Option { 81 return func(o *options) { o.logger = l } 82 } 83 84 // Run runs the tracker. 85 func Run(flags *Flags, opts ...Option) { 86 var overrides options 87 for _, o := range opts { 88 o(&overrides) 89 } 90 91 var config Config 92 if overrides.config != nil { 93 config = *overrides.config 94 } else { 95 if err := configutil.Load(flags.ConfigFile, &config); err != nil { 96 panic(err) 97 } 98 if flags.SecretsFile != "" { 99 if err := configutil.Load(flags.SecretsFile, &config); err != nil { 100 panic(err) 101 } 102 } 103 } 104 105 if overrides.logger != nil { 106 log.SetGlobalLogger(overrides.logger.Sugar()) 107 } else { 108 zlog := log.ConfigureLogger(config.ZapLogging) 109 defer zlog.Sync() 110 } 111 112 stats := overrides.metrics 113 if stats == nil { 114 s, closer, err := metrics.New(config.Metrics, flags.KrakenCluster) 115 if err != nil { 116 log.Fatalf("Failed to init metrics: %s", err) 117 } 118 stats = s 119 defer closer.Close() 120 } 121 122 go metrics.EmitVersion(stats) 123 124 peerStore, err := peerstore.NewRedisStore(config.PeerStore.Redis, clock.New()) 125 if err != nil { 126 log.Fatalf("Could not create PeerStore: %s", err) 127 } 128 129 tls, err := config.TLS.BuildClient() 130 if err != nil { 131 log.Fatalf("Error building client tls config: %s", err) 132 } 133 134 origins, err := config.Origin.Build(upstream.WithHealthCheck(healthcheck.Default(tls))) 135 if err != nil { 136 log.Fatalf("Error building origin host list: %s", err) 137 } 138 139 originStore := originstore.New( 140 config.OriginStore, clock.New(), origins, blobclient.NewProvider(blobclient.WithTLS(tls))) 141 142 policy, err := peerhandoutpolicy.NewPriorityPolicy(stats, config.PeerHandoutPolicy.Priority) 143 if err != nil { 144 log.Fatalf("Could not load peer handout policy: %s", err) 145 } 146 147 r := blobclient.NewClientResolver(blobclient.NewProvider(blobclient.WithTLS(tls)), origins) 148 originCluster := blobclient.NewClusterClient(r) 149 150 server := trackerserver.New( 151 config.TrackerServer, stats, policy, peerStore, originStore, originCluster) 152 go func() { 153 log.Fatal(server.ListenAndServe()) 154 }() 155 156 log.Info("Starting nginx...") 157 log.Fatal(nginx.Run(config.Nginx, map[string]interface{}{ 158 "port": flags.Port, 159 "server": nginx.GetServer( 160 config.TrackerServer.Listener.Net, config.TrackerServer.Listener.Addr)}, 161 nginx.WithTLS(config.TLS))) 162 }