Skip to content

Commit

Permalink
Use swsscommon API to read database configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ganglyu committed Dec 14, 2023
1 parent 88e82d4 commit 56852a4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 145 deletions.
167 changes: 42 additions & 125 deletions sonic_db_config/db_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
package dbconfig

import (
"encoding/json"
"errors"
"fmt"
io "io/ioutil"
"os"
"path/filepath"
"strconv"
"github.com/sonic-net/sonic-gnmi/swsscommon"
)

const (
Expand All @@ -18,9 +15,7 @@ const (
SONIC_DEFAULT_NAMESPACE string = ""
)

var sonic_db_config = make(map[string]map[string]interface{})
var sonic_db_init bool
var sonic_db_multi_namespace bool

func GetDbDefaultNamespace() string {
return SONIC_DEFAULT_NAMESPACE
Expand All @@ -29,30 +24,37 @@ func CheckDbMultiNamespace() bool {
if !sonic_db_init {
DbInit()
}
return sonic_db_multi_namespace
ns_vec := swsscommon.SonicDBConfigGetNamespaces()
length := int(ns_vec.Size())
return length > 1
}
func GetDbNonDefaultNamespaces() []string {
if !sonic_db_init {
DbInit()
}
ns_list := make([]string, 0, len(sonic_db_config))
for ns := range sonic_db_config {
if ns == SONIC_DEFAULT_NAMESPACE {
ns_vec := swsscommon.SonicDBConfigGetNamespaces()
length := int(ns_vec.Size())
var ns_list []string
for i := 0; i < length; i += 1 {
ns := ns_vec.Get(i)
if ns == SONIC_DEFAULT_INSTANCE {
continue
}
ns_list = append(ns_list, ns)
}
return ns_list
}

func GetDbAllNamespaces() []string {
if !sonic_db_init {
DbInit()
}
ns_list := make([]string, len(sonic_db_config))
i := 0
for ns := range sonic_db_config {
ns_list[i] = ns
i++
ns_vec := swsscommon.SonicDBConfigGetNamespaces()
length := int(ns_vec.Size())
var ns_list []string
for i := 0; i < length; i += 1 {
ns := ns_vec.Get(i)
ns_list = append(ns_list, ns)
}
return ns_list
}
Expand All @@ -69,94 +71,59 @@ func GetDbNamespaceFromTarget(target string) (string, bool) {
}
return "", false
}
func GetDbList(ns string) map[string]interface{} {
if !sonic_db_init {
DbInit()
}
db_list, ok := sonic_db_config[ns]["DATABASES"].(map[string]interface{})
if !ok {
panic(fmt.Errorf("DATABASES' is not valid key in database_config.json file for namespace `%v` !", ns))
}
return db_list
}

func GetDbInst(db_name string, ns string) map[string]interface{} {
func GetDbList(ns string) []string {
if !sonic_db_init {
DbInit()
}
db, ok := sonic_db_config[ns]["DATABASES"].(map[string]interface{})[db_name]
if !ok {
panic(fmt.Errorf("database name '%v' is not valid in database_config.json file for namespace `%v`!", db_name, ns))
}
inst_name, ok := db.(map[string]interface{})["instance"]
if !ok {
panic(fmt.Errorf("'instance' is not a valid field in database_config.json file for namespace `%v`!", ns))
db_vec := swsscommon.SonicDBConfigGetDbList()
length := int(db_vec.Size())
var db_list []string
for i := 0; i < length; i += 1 {
ns := db_vec.Get(i)
db_list = append(db_list, ns)
}
inst, ok := sonic_db_config[ns]["INSTANCES"].(map[string]interface{})[inst_name.(string)]
if !ok {
panic(fmt.Errorf("instance name '%v' is not valid in database_config.json file for namespace `%v`!", inst_name, ns))
}
return inst.(map[string]interface{})
return db_list
}

func GetDbSeparator(db_name string, ns string) string {
if !sonic_db_init {
DbInit()
}
db_list := GetDbList(ns)
separator, ok := db_list[db_name].(map[string]interface{})["separator"]
if !ok {
panic(fmt.Errorf("'separator' is not a valid field in database_config.json file!"))
}
return separator.(string)
separator := swsscommon.SonicDBConfigGetSeparator(db_name, ns)
return separator
}

func GetDbId(db_name string, ns string) int {
if !sonic_db_init {
DbInit()
}
db_list := GetDbList(ns)
id, ok := db_list[db_name].(map[string]interface{})["id"]
if !ok {
panic(fmt.Errorf("'id' is not a valid field in database_config.json file!"))
}
return int(id.(float64))
id := swsscommon.SonicDBConfigGetDbId(db_name, ns)
return id
}

func GetDbSock(db_name string, ns string) string {
if !sonic_db_init {
DbInit()
}
inst := GetDbInst(db_name, ns)
unix_socket_path, ok := inst["unix_socket_path"]
if !ok {
panic(fmt.Errorf("'unix_socket_path' is not a valid field in database_config.json file!"))
}
return unix_socket_path.(string)
unix_socket_path := swsscommon.SonicDBConfigGetDbSock(db_name, ns)
return unix_socket_path
}

func GetDbHostName(db_name string, ns string) string {
if !sonic_db_init {
DbInit()
}
inst := GetDbInst(db_name, ns)
hostname, ok := inst["hostname"]
if !ok {
panic(fmt.Errorf("'hostname' is not a valid field in database_config.json file!"))
}
return hostname.(string)
hostname := swsscommon.SonicDBConfigGetDbHostname(db_name, ns)
return hostname
}

func GetDbPort(db_name string, ns string) int {
if !sonic_db_init {
DbInit()
}
inst := GetDbInst(db_name, ns)
port, ok := inst["port"]
if !ok {
panic(fmt.Errorf("'port' is not a valid field in database_config.json file!"))
}
return int(port.(float64))
port := swsscommon.SonicDBConfigGetDbPort(db_name, ns)
return port
}

func GetDbTcpAddr(db_name string, ns string) string {
Expand All @@ -168,73 +135,23 @@ func GetDbTcpAddr(db_name string, ns string) string {
return hostname + ":" + strconv.Itoa(port)
}

func DbGetNamespaceAndConfigFile(ns_to_cfgfile_map map[string]string) {
data, err := io.ReadFile(SONIC_DB_GLOBAL_CONFIG_FILE)
if err == nil {
//Ref:https://stackoverflow.com/questions/18537257/how-to-get-the-directory-of-the-currently-running-file
dir, err := filepath.Abs(filepath.Dir(SONIC_DB_GLOBAL_CONFIG_FILE))
if err != nil {
panic(err)
}
sonic_db_global_config := make(map[string]interface{})
err = json.Unmarshal([]byte(data), &sonic_db_global_config)
if err != nil {
panic(err)
}
for _, entry := range sonic_db_global_config["INCLUDES"].([]interface{}) {
ns, ok := entry.(map[string]interface{})["namespace"]
if !ok {
ns = SONIC_DEFAULT_NAMESPACE
}
_, ok = ns_to_cfgfile_map[ns.(string)]
if ok {
panic(fmt.Errorf("Global Database config file is not valid(multiple include for same namespace!"))
}
//Ref:https://www.geeksforgeeks.org/filepath-join-function-in-golang-with-examples/
db_include_file := filepath.Join(dir, entry.(map[string]interface{})["include"].(string))
ns_to_cfgfile_map[ns.(string)] = db_include_file
}
if len(ns_to_cfgfile_map) > 1 {
sonic_db_multi_namespace = true
} else {
sonic_db_multi_namespace = false
}

} else if errors.Is(err, os.ErrNotExist) {
// Ref: https://stackoverflow.com/questions/23452157/how-do-i-check-for-specific-types-of-error-among-those-returned-by-ioutil-readfi
ns_to_cfgfile_map[SONIC_DEFAULT_NAMESPACE] = SONIC_DB_CONFIG_FILE
// Tests can override the file path via an env variable
if f, ok := os.LookupEnv("DB_CONFIG_PATH"); ok {
ns_to_cfgfile_map[SONIC_DEFAULT_NAMESPACE] = f
}
sonic_db_multi_namespace = false
} else {
panic(err)
}
}

func DbInit() {
if sonic_db_init {
return
}
ns_to_cfgfile_map := make(map[string]string)
// Ref: https://stackoverflow.com/questions/14928826/passing-pointers-to-maps-in-golang
DbGetNamespaceAndConfigFile(ns_to_cfgfile_map)
for ns, db_cfg_file := range ns_to_cfgfile_map {
data, err := io.ReadFile(db_cfg_file)
if err != nil {
panic(err)
if _, err := os.Stat(SONIC_DB_GLOBAL_CONFIG_FILE); err == nil || os.IsExist(err) {
if !swsscommon.SonicDBConfigIsGlobalInit() {
swsscommon.SonicDBConfigInitializeGlobalConfig()
}
db_config := make(map[string]interface{})
err = json.Unmarshal([]byte(data), &db_config)
if err != nil {
panic(err)
} else {
if !swsscommon.SonicDBConfigIsInit() {
swsscommon.SonicDBConfigInitialize()
}
sonic_db_config[ns] = db_config
}
sonic_db_init = true
}

func Init() {
sonic_db_init = false
swsscommon.SonicDBConfigUninitialize()
}
21 changes: 1 addition & 20 deletions sonic_db_config/db_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func TestGetDb(t *testing.T) {
}
})
}

func TestGetDbMultiNs(t *testing.T) {
Init()
err := test_utils.SetupMultiNamespace()
Expand Down Expand Up @@ -79,23 +80,3 @@ func TestGetDbMultiNs(t *testing.T) {
})
}

func TestOverrideDbConfigFile(t *testing.T) {
Init()
// Override database_config.json path to a garbage value by setting
// env DB_CONFIG_PATH and verify that GetDbId() panics
if err := os.Setenv("DB_CONFIG_PATH", "/tmp/.unknown_database_config_file.json"); err != nil {
t.Fatalf("os.Setenv failed: %v", err)
}
t.Cleanup(func() {
os.Unsetenv("DB_CONFIG_PATH")
Init()
})
defer func() {
r := recover()
if err, _ := r.(error); !os.IsNotExist(err) {
t.Fatalf("Unexpected panic: %v", r)
}
}()
_ = GetDbId("CONFIG_DB", GetDbDefaultNamespace())
t.Fatal("GetDbId() should have paniced")
}

0 comments on commit 56852a4

Please sign in to comment.