blob: 8fdfd4115ac396a6b5295dadfb7a5e6634d8e295 [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 {
47 //return err
48 return nil, errors.New("Error parsing the command line")
49 }
50 //if(!cmdParse.Parsed()) {
51 //}
Hardik Windlass9f949c92019-10-10 06:39:24 +000052
53 if val, have := os.LookupEnv("HOSTNAME"); have {
54 config.InstanceID = val
55 } else {
56 config.InstanceID = default_InstanceID
57 }
58
Scott Bakere7144bc2019-10-01 14:16:47 -070059 return config, nil
60}
61
62// Configuration file loading and parsing
63type Configuration struct {
Hardik Windlass9f949c92019-10-10 06:39:24 +000064 InstanceID string
Scott Bakere7144bc2019-10-01 14:16:47 -070065 ConfigFile *string
66 LogLevel *int
67 GrpcLog *bool
68 DisplayVersionOnly *bool
Scott Bakeredb0ae12019-10-22 08:55:12 -070069 DryRun *bool
Scott Bakere7144bc2019-10-01 14:16:47 -070070 Servers []ServerConfig `json:"servers"`
71 Ports PortConfig `json:"ports"`
72 ServerCertificates ServerCertConfig `json:"serverCertificates"`
73 ClientCertificates ClientCertConfig `json:"clientCertificates"`
74 BackendClusters []BackendClusterConfig `json:"backend_clusters"`
75 Routers []RouterConfig `json:"routers"`
76 Api ApiConfig
77}
78
79type RouterConfig struct {
80 Name string `json:"name"`
81 ProtoService string `json:"service"`
82 ProtoPackage string `json:"package"`
83 ProtoFile string `json:"proto_descriptor"`
84 Routes []RouteConfig `json:"routes"`
85 protoDescriptor descriptor.FileDescriptorSet
86}
87
88type RouteConfig struct {
89 Name string `json:"name"`
90 Type routeType `json:"type"`
91 Association associationType `json:"association"`
92 RouteField string `json:"routing_field"`
93 Methods []string `json:"methods"` // The GRPC methods to route using the route field
94 NbBindingMethods []string `json:"nb_binding_methods"`
95 BackendCluster string `json:"backend_cluster"`
96 Binding BindingConfig `json:"binding"`
97 Overrides []OverrideConfig `json:"overrides"`
98 backendCluster *BackendClusterConfig
99}
100
101type BindingConfig struct {
102 Type string `json:"type"`
103 Field string `json:"field"`
104 Method string `json:"method"`
105 Association associationType `json:"association"`
106}
107
108type OverrideConfig struct {
109 Methods []string `json:"methods"`
110 Method string `json:"method"`
111 RouteField string `json:"routing_field"`
112}
113
114// Backend configuration
115
116type BackendClusterConfig struct {
117 Name string `json:"name"`
118 Backends []BackendConfig `json:"backends"`
119}
120
121type BackendConfig struct {
122 Name string `json:"name"`
123 Type backendType `json:"type"`
124 Association AssociationConfig `json:"association"`
125 Connections []ConnectionConfig `json:"connections"`
126}
127
128type AssociationConfig struct {
129 Strategy associationStrategy `json:"strategy"`
130 Location associationLocation `json:"location"`
131 Field string `json:"field"`
132 Key string `json:"key"`
133}
134
135type ConnectionConfig struct {
136 Name string `json:"name"`
137 Addr string `json:"addr"`
138 Port string `json:"port"`
139}
140
141// Server configuration
142
143type ServerConfig struct {
144 Name string `json:"name"`
145 Port uint `json:"port"`
146 Addr string `json:"address"`
147 Type string `json:"type"`
148 Routers []RouterPackage `json:"routers"`
149 routers map[string]*RouterConfig
150}
151
152type RouterPackage struct {
153 Router string `json:"router"`
154 Package string `json:"package"`
155}
156
157// Port configuration
158type PortConfig struct {
159 GrpcPort uint `json:"grpcPort"`
160 StreamingGrpcPort uint `json:"streamingGrpcPort"`
161 TlsGrpcPort uint `json:"tlsGrpcPort"`
162 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
163 ControlPort uint `json:"controlPort"`
164}
165
166// Server Certificate configuration
167type ServerCertConfig struct {
168 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
169 GrpcKey string `json:"grpcKey"` // File path to the key file
170 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
171}
172
173// Client Certificate configuration
174type ClientCertConfig struct {
175 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
176 GrpcKey string `json:"grpcKey"` // File path to the key file
177 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
178}
179
180// Api configuration
181type ApiConfig struct {
182 Addr string `json:"address"`
183 Port uint `json:"port"`
184}
185
186func (conf *Configuration) LoadConfig() error {
187
188 configF, err := os.Open(*conf.ConfigFile)
189 log.Info("Loading configuration from: ", *conf.ConfigFile)
190 if err != nil {
191 log.Error(err)
192 return err
193 }
194
195 defer configF.Close()
196
197 configBytes, err := ioutil.ReadAll(configF)
198 if err != nil {
199 log.Error(err)
200 return err
201 }
202
203 if err := json.Unmarshal(configBytes, conf); err != nil {
204 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
205 return err
206 }
207
208 // Now resolve references to different config objects in the
209 // config file. Currently there are 2 possible references
210 // to resolve: referecnes to routers in the servers, and
211 // references to backend_cluster in the routers.
212
213 // Resolve router references for the servers
214 log.Debug("Resolving references in the config file")
215 for k := range conf.Servers {
216 //s.routers =make(map[string]*RouterConfig)
217 conf.Servers[k].routers = make(map[string]*RouterConfig)
218 for _, rPkg := range conf.Servers[k].Routers {
219 var found = false
220 // Locate the router "r" in the top lever Routers array
221 log.Debugf("Resolving router reference to router '%s' from server '%s'", rPkg.Router, conf.Servers[k].Name)
222 for rk := range conf.Routers {
223 if conf.Routers[rk].Name == rPkg.Router && !found {
224 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
225 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
226 found = true
227 } else if conf.Routers[rk].Name == rPkg.Router && found {
228 if _, ok := conf.Servers[k].routers[rPkg.Package]; !ok {
229 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
230 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
231 } else {
Scott Baker4989fe92019-10-09 17:03:06 -0700232 err := fmt.Errorf("Duplicate router '%s' defined for package '%s'", rPkg.Router, rPkg.Package)
Scott Bakere7144bc2019-10-01 14:16:47 -0700233 log.Error(err)
234 return err
235 }
236 }
237 }
238 if !found {
Scott Baker4989fe92019-10-09 17:03:06 -0700239 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 -0700240 log.Error(err)
241 return err
242 }
243 }
244 }
245
246 // Resolve backend references for the routers
247 for rk, rv := range conf.Routers {
248 for rtk, rtv := range rv.Routes {
249 var found = false
250 log.Debugf("Resolving backend reference to %s from router %s", rtv.BackendCluster, rv.Name)
251 for bek, bev := range conf.BackendClusters {
252 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
253 if rtv.BackendCluster == bev.Name && !found {
254 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
255 found = true
256 } else if rtv.BackendCluster == bev.Name && found {
Scott Baker4989fe92019-10-09 17:03:06 -0700257 err := fmt.Errorf("Duplicate backend defined, %s", conf.BackendClusters[bek].Name)
Scott Bakere7144bc2019-10-01 14:16:47 -0700258 log.Error(err)
259 return err
260 }
261 }
262 if !found {
Scott Baker4989fe92019-10-09 17:03:06 -0700263 err := fmt.Errorf("Backend %s for router %s not found in config",
264 rtv.BackendCluster, rv.Name)
Scott Bakere7144bc2019-10-01 14:16:47 -0700265 log.Error(err)
266 return err
267 }
268 }
269 }
270
271 return nil
272}