blob: 044fdd7330d5426e25417c2352f046e4f2590c2e [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"
sslobodr392ebd52019-01-18 12:41:49 -050025 "github.com/opencord/voltha-go/common/log"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040026 "io/ioutil"
27 "os"
28 "path"
sslobodr392ebd52019-01-18 12:41:49 -050029)
30
31func ParseCmd() (*Configuration, error) {
32 config := &Configuration{}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040033 cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError)
sslobodr392ebd52019-01-18 12:41:49 -050034 config.ConfigFile = cmdParse.String("config", "arouter.json", "The configuration file for the affinity router")
35 config.LogLevel = cmdParse.Int("logLevel", 0, "The log level for the affinity router")
36 config.GrpcLog = cmdParse.Bool("grpclog", false, "Enable GRPC logging")
37
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040038 err := cmdParse.Parse(os.Args[1:])
sslobodr3d587c62019-01-24 12:33:39 -050039 if err != nil {
sslobodr392ebd52019-01-18 12:41:49 -050040 //return err
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040041 return nil, errors.New("Error parsing the command line")
sslobodr392ebd52019-01-18 12:41:49 -050042 }
43 //if(!cmdParse.Parsed()) {
44 //}
45 return config, nil
46}
47
48// Configuration file loading and parsing
49type Configuration struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040050 ConfigFile *string
51 LogLevel *int
52 GrpcLog *bool
53 Servers []ServerConfig `json:"servers"`
54 Ports PortConfig `json:"ports"`
55 ServerCertificates ServerCertConfig `json:"serverCertificates"`
56 ClientCertificates ClientCertConfig `json:"clientCertificates"`
57 BackendClusters []BackendClusterConfig `json:"backend_clusters"`
58 Routers []RouterConfig `json:"routers"`
59 Api ApiConfig
sslobodr392ebd52019-01-18 12:41:49 -050060}
61
62type RouterConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040063 Name string `json:"name"`
64 ProtoService string `json:"service"`
65 ProtoPackage string `json:"package"`
66 Routes []RouteConfig `json:"routes"`
sslobodr392ebd52019-01-18 12:41:49 -050067}
68
69type RouteConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040070 Name string `json:"name"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -040071 Type routeType `json:"type"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040072 ProtoFile string `json:"proto_descriptor"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -040073 Association associationType `json:"association"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040074 RouteField string `json:"routing_field"`
75 Methods []string `json:"methods"` // The GRPC methods to route using the route field
76 NbBindingMethods []string `json:"nb_binding_methods"`
77 BackendCluster string `json:"backend_cluster"`
78 Binding BindingConfig `json:"binding"`
79 Overrides []OverrideConfig `json:"overrides"`
80 backendCluster *BackendClusterConfig
sslobodr392ebd52019-01-18 12:41:49 -050081}
82
83type BindingConfig struct {
Kent Hagerman1e9061e2019-05-21 16:01:21 -040084 Type string `json:"type"`
85 Field string `json:"field"`
86 Method string `json:"method"`
87 Association associationType `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -050088}
89
90type OverrideConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040091 Methods []string `json:"methods"`
92 Method string `json:"method"`
93 RouteField string `json:"routing_field"`
sslobodr392ebd52019-01-18 12:41:49 -050094}
95
96// Backend configuration
97
98type BackendClusterConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040099 Name string `json:"name"`
sslobodr392ebd52019-01-18 12:41:49 -0500100 Backends []BackendConfig `json:"backends"`
101}
102
103type BackendConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400104 Name string `json:"name"`
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400105 Type backendType `json:"type"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400106 Association AssociationConfig `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -0500107 Connections []ConnectionConfig `json:"connections"`
108}
109
110type AssociationConfig struct {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400111 Strategy associationStrategy `json:"strategy"`
112 Location associationLocation `json:"location"`
113 Field string `json:"field"`
114 Key string `json:"key"`
sslobodr392ebd52019-01-18 12:41:49 -0500115}
116
117type ConnectionConfig struct {
118 Name string `json:"name"`
119 Addr string `json:"addr"`
120 Port string `json:"port"`
121}
122
123// Server configuration
124
125type ServerConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400126 Name string `json:"name"`
127 Port uint `json:"port"`
128 Addr string `json:"address"`
129 Type string `json:"type"`
sslobodr392ebd52019-01-18 12:41:49 -0500130 Routers []RouterPackage `json:"routers"`
131 routers map[string]*RouterConfig
132}
133
134type RouterPackage struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400135 Router string `json:"router"`
sslobodr392ebd52019-01-18 12:41:49 -0500136 Package string `json:"package"`
137}
138
139// Port configuration
140type PortConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400141 GrpcPort uint `json:"grpcPort"`
142 StreamingGrpcPort uint `json:"streamingGrpcPort"`
143 TlsGrpcPort uint `json:"tlsGrpcPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500144 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400145 ControlPort uint `json:"controlPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500146}
147
148// Server Certificate configuration
149type ServerCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400150 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
151 GrpcKey string `json:"grpcKey"` // File path to the key file
152 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500153}
154
155// Client Certificate configuration
156type ClientCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400157 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
158 GrpcKey string `json:"grpcKey"` // File path to the key file
159 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500160}
161
162// Api configuration
163type ApiConfig struct {
164 Addr string `json:"address"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400165 Port uint `json:"port"`
sslobodr392ebd52019-01-18 12:41:49 -0500166}
167
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400168func (conf *Configuration) LoadConfig() error {
sslobodr392ebd52019-01-18 12:41:49 -0500169
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400170 configF, err := os.Open(*conf.ConfigFile)
sslobodr392ebd52019-01-18 12:41:49 -0500171 log.Info("Loading configuration from: ", *conf.ConfigFile)
172 if err != nil {
173 log.Error(err)
174 return err
175 }
176
177 defer configF.Close()
178
179 configBytes, err := ioutil.ReadAll(configF)
180 if err != nil {
181 log.Error(err)
182 return err
183 }
184
sslobodr8e2ccb52019-02-05 09:21:47 -0500185 if err := json.Unmarshal(configBytes, conf); err != nil {
186 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
187 return err
188 }
sslobodr392ebd52019-01-18 12:41:49 -0500189
190 // Now resolve references to different config objects in the
191 // config file. Currently there are 2 possible references
192 // to resolve: referecnes to routers in the servers, and
193 // references to backend_cluster in the routers.
194
195 // Resolve router references for the servers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400196 log.Debug("Resolving references in the config file")
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400197 for k := range conf.Servers {
sslobodr392ebd52019-01-18 12:41:49 -0500198 //s.routers =make(map[string]*RouterConfig)
199 conf.Servers[k].routers = make(map[string]*RouterConfig)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400200 for _, rPkg := range conf.Servers[k].Routers {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400201 var found = false
sslobodr392ebd52019-01-18 12:41:49 -0500202 // Locate the router "r" in the top lever Routers array
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400203 log.Debugf("Resolving router reference to router '%s' from server '%s'", rPkg.Router, conf.Servers[k].Name)
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400204 for rk := range conf.Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500205 if conf.Routers[rk].Name == rPkg.Router && !found {
206 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
207 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
208 found = true
209 } else if conf.Routers[rk].Name == rPkg.Router && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400210 if _, ok := conf.Servers[k].routers[rPkg.Package]; !ok {
sslobodr392ebd52019-01-18 12:41:49 -0500211 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
212 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
213 } else {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400214 err := errors.New(fmt.Sprintf("Duplicate router '%s' defined for package '%s'", rPkg.Router, rPkg.Package))
sslobodr392ebd52019-01-18 12:41:49 -0500215 log.Error(err)
216 return err
217 }
218 }
219 }
220 if !found {
221 err := errors.New(fmt.Sprintf("Router %s for server %s not found in config", conf.Servers[k].Name, rPkg.Router))
222 log.Error(err)
223 return err
224 }
225 }
226 }
227
228 // Resolve backend references for the routers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400229 for rk, rv := range conf.Routers {
230 for rtk, rtv := range rv.Routes {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400231 var found = false
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400232 log.Debugf("Resolving backend reference to %s from router %s", rtv.BackendCluster, rv.Name)
233 for bek, bev := range conf.BackendClusters {
sslobodr392ebd52019-01-18 12:41:49 -0500234 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
235 if rtv.BackendCluster == bev.Name && !found {
236 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
237 found = true
238 } else if rtv.BackendCluster == bev.Name && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400239 err := errors.New(fmt.Sprintf("Duplicate backend defined, %s", conf.BackendClusters[bek].Name))
sslobodr392ebd52019-01-18 12:41:49 -0500240 log.Error(err)
241 return err
242 }
243 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400244 if !found {
sslobodr392ebd52019-01-18 12:41:49 -0500245 err := errors.New(fmt.Sprintf("Backend %s for router %s not found in config",
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400246 rtv.BackendCluster, rv.Name))
sslobodr392ebd52019-01-18 12:41:49 -0500247 log.Error(err)
248 return err
249 }
250 }
251 }
252
sslobodr392ebd52019-01-18 12:41:49 -0500253 return nil
254}