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