blob: 60081997cf5f1b36e3c2f0b29b628ac3f8009958 [file] [log] [blame]
sslobodr392ebd52019-01-18 12:41:49 -05001/*
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 */
sslobodr392ebd52019-01-18 12:41:49 -050016
17package afrouter
18
19// Command line parameters and parsing
20import (
sslobodr392ebd52019-01-18 12:41:49 -050021 "encoding/json"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040022 "errors"
23 "flag"
24 "fmt"
Kent Hagerman70a49bb2019-08-29 17:21:03 -040025 "github.com/golang/protobuf/protoc-gen-go/descriptor"
sslobodr392ebd52019-01-18 12:41:49 -050026 "github.com/opencord/voltha-go/common/log"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040027 "io/ioutil"
28 "os"
29 "path"
sslobodr392ebd52019-01-18 12:41:49 -050030)
31
32func ParseCmd() (*Configuration, error) {
33 config := &Configuration{}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040034 cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError)
sslobodr392ebd52019-01-18 12:41:49 -050035 config.ConfigFile = cmdParse.String("config", "arouter.json", "The configuration file for the affinity router")
36 config.LogLevel = cmdParse.Int("logLevel", 0, "The log level for the affinity router")
37 config.GrpcLog = cmdParse.Bool("grpclog", false, "Enable GRPC logging")
David K. Bainbridgef430cd52019-05-28 15:00:35 -070038 config.DisplayVersionOnly = cmdParse.Bool("version", false, "Print version information and exit")
sslobodr392ebd52019-01-18 12:41:49 -050039
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040040 err := cmdParse.Parse(os.Args[1:])
sslobodr3d587c62019-01-24 12:33:39 -050041 if err != nil {
sslobodr392ebd52019-01-18 12:41:49 -050042 //return err
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040043 return nil, errors.New("Error parsing the command line")
sslobodr392ebd52019-01-18 12:41:49 -050044 }
45 //if(!cmdParse.Parsed()) {
46 //}
47 return config, nil
48}
49
50// Configuration file loading and parsing
51type Configuration struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040052 ConfigFile *string
53 LogLevel *int
54 GrpcLog *bool
David K. Bainbridgef430cd52019-05-28 15:00:35 -070055 DisplayVersionOnly *bool
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040056 Servers []ServerConfig `json:"servers"`
57 Ports PortConfig `json:"ports"`
58 ServerCertificates ServerCertConfig `json:"serverCertificates"`
59 ClientCertificates ClientCertConfig `json:"clientCertificates"`
60 BackendClusters []BackendClusterConfig `json:"backend_clusters"`
61 Routers []RouterConfig `json:"routers"`
62 Api ApiConfig
sslobodr392ebd52019-01-18 12:41:49 -050063}
64
65type RouterConfig struct {
Kent Hagerman70a49bb2019-08-29 17:21:03 -040066 Name string `json:"name"`
67 ProtoService string `json:"service"`
68 ProtoPackage string `json:"package"`
69 ProtoFile string `json:"proto_descriptor"`
70 Routes []RouteConfig `json:"routes"`
71 protoDescriptor descriptor.FileDescriptorSet
sslobodr392ebd52019-01-18 12:41:49 -050072}
73
74type RouteConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040075 Name string `json:"name"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -040076 Type routeType `json:"type"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -040077 Association associationType `json:"association"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040078 RouteField string `json:"routing_field"`
79 Methods []string `json:"methods"` // The GRPC methods to route using the route field
80 NbBindingMethods []string `json:"nb_binding_methods"`
81 BackendCluster string `json:"backend_cluster"`
82 Binding BindingConfig `json:"binding"`
83 Overrides []OverrideConfig `json:"overrides"`
84 backendCluster *BackendClusterConfig
sslobodr392ebd52019-01-18 12:41:49 -050085}
86
87type BindingConfig struct {
Kent Hagerman1e9061e2019-05-21 16:01:21 -040088 Type string `json:"type"`
89 Field string `json:"field"`
90 Method string `json:"method"`
91 Association associationType `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -050092}
93
94type OverrideConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040095 Methods []string `json:"methods"`
96 Method string `json:"method"`
97 RouteField string `json:"routing_field"`
sslobodr392ebd52019-01-18 12:41:49 -050098}
99
100// Backend configuration
101
102type BackendClusterConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400103 Name string `json:"name"`
sslobodr392ebd52019-01-18 12:41:49 -0500104 Backends []BackendConfig `json:"backends"`
105}
106
107type BackendConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400108 Name string `json:"name"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400109 Type backendType `json:"type"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400110 Association AssociationConfig `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -0500111 Connections []ConnectionConfig `json:"connections"`
112}
113
114type AssociationConfig struct {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400115 Strategy associationStrategy `json:"strategy"`
116 Location associationLocation `json:"location"`
117 Field string `json:"field"`
118 Key string `json:"key"`
sslobodr392ebd52019-01-18 12:41:49 -0500119}
120
121type ConnectionConfig struct {
122 Name string `json:"name"`
123 Addr string `json:"addr"`
124 Port string `json:"port"`
125}
126
127// Server configuration
128
129type ServerConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400130 Name string `json:"name"`
131 Port uint `json:"port"`
132 Addr string `json:"address"`
133 Type string `json:"type"`
sslobodr392ebd52019-01-18 12:41:49 -0500134 Routers []RouterPackage `json:"routers"`
135 routers map[string]*RouterConfig
136}
137
138type RouterPackage struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400139 Router string `json:"router"`
sslobodr392ebd52019-01-18 12:41:49 -0500140 Package string `json:"package"`
141}
142
143// Port configuration
144type PortConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400145 GrpcPort uint `json:"grpcPort"`
146 StreamingGrpcPort uint `json:"streamingGrpcPort"`
147 TlsGrpcPort uint `json:"tlsGrpcPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500148 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400149 ControlPort uint `json:"controlPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500150}
151
152// Server Certificate configuration
153type ServerCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400154 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
155 GrpcKey string `json:"grpcKey"` // File path to the key file
156 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500157}
158
159// Client Certificate configuration
160type ClientCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400161 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
162 GrpcKey string `json:"grpcKey"` // File path to the key file
163 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500164}
165
166// Api configuration
167type ApiConfig struct {
168 Addr string `json:"address"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400169 Port uint `json:"port"`
sslobodr392ebd52019-01-18 12:41:49 -0500170}
171
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400172func (conf *Configuration) LoadConfig() error {
sslobodr392ebd52019-01-18 12:41:49 -0500173
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400174 configF, err := os.Open(*conf.ConfigFile)
sslobodr392ebd52019-01-18 12:41:49 -0500175 log.Info("Loading configuration from: ", *conf.ConfigFile)
176 if err != nil {
177 log.Error(err)
178 return err
179 }
180
181 defer configF.Close()
182
183 configBytes, err := ioutil.ReadAll(configF)
184 if err != nil {
185 log.Error(err)
186 return err
187 }
188
sslobodr8e2ccb52019-02-05 09:21:47 -0500189 if err := json.Unmarshal(configBytes, conf); err != nil {
190 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
191 return err
192 }
sslobodr392ebd52019-01-18 12:41:49 -0500193
194 // Now resolve references to different config objects in the
195 // config file. Currently there are 2 possible references
196 // to resolve: referecnes to routers in the servers, and
197 // references to backend_cluster in the routers.
198
199 // Resolve router references for the servers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400200 log.Debug("Resolving references in the config file")
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400201 for k := range conf.Servers {
sslobodr392ebd52019-01-18 12:41:49 -0500202 //s.routers =make(map[string]*RouterConfig)
203 conf.Servers[k].routers = make(map[string]*RouterConfig)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400204 for _, rPkg := range conf.Servers[k].Routers {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400205 var found = false
sslobodr392ebd52019-01-18 12:41:49 -0500206 // Locate the router "r" in the top lever Routers array
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400207 log.Debugf("Resolving router reference to router '%s' from server '%s'", rPkg.Router, conf.Servers[k].Name)
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400208 for rk := range conf.Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500209 if conf.Routers[rk].Name == rPkg.Router && !found {
210 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
211 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
212 found = true
213 } else if conf.Routers[rk].Name == rPkg.Router && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400214 if _, ok := conf.Servers[k].routers[rPkg.Package]; !ok {
sslobodr392ebd52019-01-18 12:41:49 -0500215 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
216 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
217 } else {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400218 err := errors.New(fmt.Sprintf("Duplicate router '%s' defined for package '%s'", rPkg.Router, rPkg.Package))
sslobodr392ebd52019-01-18 12:41:49 -0500219 log.Error(err)
220 return err
221 }
222 }
223 }
224 if !found {
225 err := errors.New(fmt.Sprintf("Router %s for server %s not found in config", conf.Servers[k].Name, rPkg.Router))
226 log.Error(err)
227 return err
228 }
229 }
230 }
231
232 // Resolve backend references for the routers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400233 for rk, rv := range conf.Routers {
234 for rtk, rtv := range rv.Routes {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400235 var found = false
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400236 log.Debugf("Resolving backend reference to %s from router %s", rtv.BackendCluster, rv.Name)
237 for bek, bev := range conf.BackendClusters {
sslobodr392ebd52019-01-18 12:41:49 -0500238 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
239 if rtv.BackendCluster == bev.Name && !found {
240 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
241 found = true
242 } else if rtv.BackendCluster == bev.Name && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400243 err := errors.New(fmt.Sprintf("Duplicate backend defined, %s", conf.BackendClusters[bek].Name))
sslobodr392ebd52019-01-18 12:41:49 -0500244 log.Error(err)
245 return err
246 }
247 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400248 if !found {
sslobodr392ebd52019-01-18 12:41:49 -0500249 err := errors.New(fmt.Sprintf("Backend %s for router %s not found in config",
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400250 rtv.BackendCluster, rv.Name))
sslobodr392ebd52019-01-18 12:41:49 -0500251 log.Error(err)
252 return err
253 }
254 }
255 }
256
sslobodr392ebd52019-01-18 12:41:49 -0500257 return nil
258}