blob: 3a61e63bd3b04c58d1c8f720204914e9a602b475 [file] [log] [blame]
Scott Bakere7144bc2019-10-01 14:16:47 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package afrouter
18
19// Command line parameters and parsing
20import (
21 "encoding/json"
22 "errors"
23 "flag"
24 "fmt"
25 "github.com/golang/protobuf/protoc-gen-go/descriptor"
Scott Bakerf579f132019-10-24 14:31:41 -070026 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Bakere7144bc2019-10-01 14:16:47 -070027 "io/ioutil"
28 "os"
29 "path"
30)
31
Hardik Windlass9f949c92019-10-10 06:39:24 +000032const (
33 default_InstanceID = "arouter001"
34)
35
Scott Bakere7144bc2019-10-01 14:16:47 -070036func ParseCmd() (*Configuration, error) {
37 config := &Configuration{}
38 cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError)
39 config.ConfigFile = cmdParse.String("config", "arouter.json", "The configuration file for the affinity router")
40 config.LogLevel = cmdParse.Int("logLevel", 0, "The log level for the affinity router")
41 config.GrpcLog = cmdParse.Bool("grpclog", false, "Enable GRPC logging")
42 config.DisplayVersionOnly = cmdParse.Bool("version", false, "Print version information and exit")
Scott Bakeredb0ae12019-10-22 08:55:12 -070043 config.DryRun = cmdParse.Bool("dry-run", false, "Verify config file, but exit before starting to serve requests")
Scott Bakere7144bc2019-10-01 14:16:47 -070044
45 err := cmdParse.Parse(os.Args[1:])
46 if err != nil {
Scott Bakere7144bc2019-10-01 14:16:47 -070047 return nil, errors.New("Error parsing the command line")
48 }
Hardik Windlass9f949c92019-10-10 06:39:24 +000049
50 if val, have := os.LookupEnv("HOSTNAME"); have {
51 config.InstanceID = val
52 } else {
53 config.InstanceID = default_InstanceID
54 }
55
Scott Bakere7144bc2019-10-01 14:16:47 -070056 return config, nil
57}
58
59// Configuration file loading and parsing
60type Configuration struct {
Hardik Windlass9f949c92019-10-10 06:39:24 +000061 InstanceID string
Scott Bakere7144bc2019-10-01 14:16:47 -070062 ConfigFile *string
63 LogLevel *int
64 GrpcLog *bool
65 DisplayVersionOnly *bool
Scott Bakeredb0ae12019-10-22 08:55:12 -070066 DryRun *bool
Scott Bakere7144bc2019-10-01 14:16:47 -070067 Servers []ServerConfig `json:"servers"`
68 Ports PortConfig `json:"ports"`
69 ServerCertificates ServerCertConfig `json:"serverCertificates"`
70 ClientCertificates ClientCertConfig `json:"clientCertificates"`
71 BackendClusters []BackendClusterConfig `json:"backend_clusters"`
72 Routers []RouterConfig `json:"routers"`
73 Api ApiConfig
74}
75
76type RouterConfig struct {
77 Name string `json:"name"`
78 ProtoService string `json:"service"`
79 ProtoPackage string `json:"package"`
80 ProtoFile string `json:"proto_descriptor"`
81 Routes []RouteConfig `json:"routes"`
82 protoDescriptor descriptor.FileDescriptorSet
83}
84
85type RouteConfig struct {
86 Name string `json:"name"`
87 Type routeType `json:"type"`
88 Association associationType `json:"association"`
89 RouteField string `json:"routing_field"`
90 Methods []string `json:"methods"` // The GRPC methods to route using the route field
91 NbBindingMethods []string `json:"nb_binding_methods"`
92 BackendCluster string `json:"backend_cluster"`
93 Binding BindingConfig `json:"binding"`
94 Overrides []OverrideConfig `json:"overrides"`
95 backendCluster *BackendClusterConfig
96}
97
98type BindingConfig struct {
99 Type string `json:"type"`
100 Field string `json:"field"`
101 Method string `json:"method"`
102 Association associationType `json:"association"`
103}
104
105type OverrideConfig struct {
106 Methods []string `json:"methods"`
107 Method string `json:"method"`
108 RouteField string `json:"routing_field"`
109}
110
111// Backend configuration
112
113type BackendClusterConfig struct {
114 Name string `json:"name"`
115 Backends []BackendConfig `json:"backends"`
116}
117
118type BackendConfig struct {
119 Name string `json:"name"`
120 Type backendType `json:"type"`
121 Association AssociationConfig `json:"association"`
122 Connections []ConnectionConfig `json:"connections"`
123}
124
125type AssociationConfig struct {
126 Strategy associationStrategy `json:"strategy"`
127 Location associationLocation `json:"location"`
128 Field string `json:"field"`
129 Key string `json:"key"`
130}
131
132type ConnectionConfig struct {
133 Name string `json:"name"`
134 Addr string `json:"addr"`
135 Port string `json:"port"`
136}
137
138// Server configuration
139
140type ServerConfig struct {
141 Name string `json:"name"`
142 Port uint `json:"port"`
143 Addr string `json:"address"`
144 Type string `json:"type"`
145 Routers []RouterPackage `json:"routers"`
146 routers map[string]*RouterConfig
147}
148
149type RouterPackage struct {
150 Router string `json:"router"`
151 Package string `json:"package"`
152}
153
154// Port configuration
155type PortConfig struct {
156 GrpcPort uint `json:"grpcPort"`
157 StreamingGrpcPort uint `json:"streamingGrpcPort"`
158 TlsGrpcPort uint `json:"tlsGrpcPort"`
159 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
160 ControlPort uint `json:"controlPort"`
161}
162
163// Server Certificate configuration
164type ServerCertConfig struct {
165 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
166 GrpcKey string `json:"grpcKey"` // File path to the key file
167 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
168}
169
170// Client Certificate configuration
171type ClientCertConfig struct {
172 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
173 GrpcKey string `json:"grpcKey"` // File path to the key file
174 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
175}
176
177// Api configuration
178type ApiConfig struct {
divyadesaif117fc22019-11-04 06:32:01 +0000179 Addr string `json:"address"`
180 Port uint `json:"port"`
181 ProbeHost string `json:"probeHost"`
182 ProbePort int `json:"probePort"`
Scott Bakere7144bc2019-10-01 14:16:47 -0700183}
184
185func (conf *Configuration) LoadConfig() error {
186
187 configF, err := os.Open(*conf.ConfigFile)
188 log.Info("Loading configuration from: ", *conf.ConfigFile)
189 if err != nil {
190 log.Error(err)
191 return err
192 }
193
194 defer configF.Close()
195
196 configBytes, err := ioutil.ReadAll(configF)
197 if err != nil {
198 log.Error(err)
199 return err
200 }
201
202 if err := json.Unmarshal(configBytes, conf); err != nil {
203 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
204 return err
205 }
206
207 // Now resolve references to different config objects in the
208 // config file. Currently there are 2 possible references
209 // to resolve: referecnes to routers in the servers, and
210 // references to backend_cluster in the routers.
211
212 // Resolve router references for the servers
213 log.Debug("Resolving references in the config file")
214 for k := range conf.Servers {
215 //s.routers =make(map[string]*RouterConfig)
216 conf.Servers[k].routers = make(map[string]*RouterConfig)
217 for _, rPkg := range conf.Servers[k].Routers {
218 var found = false
219 // Locate the router "r" in the top lever Routers array
220 log.Debugf("Resolving router reference to router '%s' from server '%s'", rPkg.Router, conf.Servers[k].Name)
221 for rk := range conf.Routers {
222 if conf.Routers[rk].Name == rPkg.Router && !found {
223 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
224 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
225 found = true
226 } else if conf.Routers[rk].Name == rPkg.Router && found {
227 if _, ok := conf.Servers[k].routers[rPkg.Package]; !ok {
228 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
229 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
230 } else {
Scott Baker4989fe92019-10-09 17:03:06 -0700231 err := fmt.Errorf("Duplicate router '%s' defined for package '%s'", rPkg.Router, rPkg.Package)
Scott Bakere7144bc2019-10-01 14:16:47 -0700232 log.Error(err)
233 return err
234 }
235 }
236 }
237 if !found {
Scott Baker4989fe92019-10-09 17:03:06 -0700238 err := fmt.Errorf("Router %s for server %s not found in config", conf.Servers[k].Name, rPkg.Router)
Scott Bakere7144bc2019-10-01 14:16:47 -0700239 log.Error(err)
240 return err
241 }
242 }
243 }
244
245 // Resolve backend references for the routers
246 for rk, rv := range conf.Routers {
247 for rtk, rtv := range rv.Routes {
248 var found = false
249 log.Debugf("Resolving backend reference to %s from router %s", rtv.BackendCluster, rv.Name)
250 for bek, bev := range conf.BackendClusters {
251 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
252 if rtv.BackendCluster == bev.Name && !found {
253 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
254 found = true
255 } else if rtv.BackendCluster == bev.Name && found {
Scott Baker4989fe92019-10-09 17:03:06 -0700256 err := fmt.Errorf("Duplicate backend defined, %s", conf.BackendClusters[bek].Name)
Scott Bakere7144bc2019-10-01 14:16:47 -0700257 log.Error(err)
258 return err
259 }
260 }
261 if !found {
Scott Baker4989fe92019-10-09 17:03:06 -0700262 err := fmt.Errorf("Backend %s for router %s not found in config",
263 rtv.BackendCluster, rv.Name)
Scott Bakere7144bc2019-10-01 14:16:47 -0700264 log.Error(err)
265 return err
266 }
267 }
268 }
269
270 return nil
271}