config/config_map_builder.go (101 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package config
import (
"encoding/json"
"log"
"os"
)
type configMapBuilder struct {
configJsonPath string
opsRootPath string
pluginOpsRoots map[string]string
}
func NewConfigMapBuilder() *configMapBuilder {
return &configMapBuilder{
pluginOpsRoots: make(map[string]string),
}
}
// WithConfigJson adds a config.json file that will be read and used
// to build a ConfigMap. If there both a config.json and a opsroot.json are
// added, the 2 configs will be merged. It assumes the input file
// is valid.
func (b *configMapBuilder) WithConfigJson(file string) *configMapBuilder {
b.configJsonPath = file
return b
}
// WithOpsRoot works like WithConfigJson, with the difference that
// the OpsRoot is read and only it's inner "config":{} object is parsed
// ignoring the rest of the content.
func (b *configMapBuilder) WithOpsRoot(file string) *configMapBuilder {
b.opsRootPath = file
return b
}
// WithPluginOpsRoots works like WithPluginOpsRoot, but it allows to add multiple
// plugin opsroot.json files at once.
func (b *configMapBuilder) WithPluginOpsRoots(nrts map[string]string) *configMapBuilder {
b.pluginOpsRoots = nrts
return b
}
func (b *configMapBuilder) Build() (ConfigMap, error) {
configJsonMap, err := readConfig(b.configJsonPath, fromConfigJson)
if err != nil {
return ConfigMap{}, err
}
opsRootMap, err := readConfig(b.opsRootPath, fromOpsRoot)
if err != nil {
return ConfigMap{}, err
}
pluginOpsRootConfigs := make(map[string]map[string]interface{}, 0)
for plgName, opsRootPath := range b.pluginOpsRoots {
pluginOpsRootMap, err := readConfig(opsRootPath, fromOpsRoot)
if err != nil {
return ConfigMap{}, err
}
pluginOpsRootConfigs[plgName] = pluginOpsRootMap
}
return ConfigMap{
pluginOpsRootConfigs: pluginOpsRootConfigs,
opsRootConfig: opsRootMap,
config: configJsonMap,
configPath: b.configJsonPath,
}, nil
}
func readConfig(path string, read func(string) (map[string]interface{}, error)) (map[string]interface{}, error) {
if path == "" {
return make(map[string]interface{}), nil
}
_, err := os.Stat(path)
if os.IsNotExist(err) {
return make(map[string]interface{}), nil
}
if err != nil {
return nil, err
}
cMap, err := read(path)
if err != nil {
return nil, err
}
return cMap, nil
}
func fromConfigJson(configPath string) (map[string]interface{}, error) {
data := make(map[string]interface{})
json_buf, err := os.ReadFile(configPath)
if err != nil {
return data, err
}
if err := json.Unmarshal(json_buf, &data); err != nil {
if data == nil {
return data, err
}
log.Println("config.json parsed with an error", err)
}
return data, nil
}
func fromOpsRoot(opsRootPath string) (map[string]interface{}, error) {
data := make(map[string]interface{})
json_buf, err := os.ReadFile(opsRootPath)
if err != nil {
return data, err
}
if err := json.Unmarshal(json_buf, &data); err != nil {
if data == nil {
return data, err
}
log.Println("opsroot.json parsed with an error", err)
}
cm, ok := data["config"].(map[string]interface{})
if !ok {
return nil, nil
}
return cm, nil
}