config/config_tool.go (135 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 (
"flag"
"fmt"
"os"
"strings"
)
func printConfigToolUsage() {
fmt.Print(`Usage:
ops -config [options] [KEY | KEY=VALUE [KEY=VALUE ...]]
Set config values passed as key-value pairs.
If the keys are passed (without '='), their values are printed, if they exists.
If you want to override a value, pass KEY="". This can be used to disable values in opsroot.json.
Removing values from opsroot.json is not supported, disable them instead.
-h, --help show this help
-r, --remove remove config values by passing keys
-d, --dump dump the configs
`)
}
func ConfigTool(configMap ConfigMap) error {
flag := flag.NewFlagSet("config", flag.ExitOnError)
var helpFlag bool
var dumpFlag bool
var removeFlag bool
flag.Usage = printConfigToolUsage
flag.BoolVar(&helpFlag, "h", false, "show this help")
flag.BoolVar(&helpFlag, "help", false, "show this help")
flag.BoolVar(&dumpFlag, "dump", false, "dump the config file")
flag.BoolVar(&dumpFlag, "d", false, "dump the config file")
flag.BoolVar(&removeFlag, "remove", false, "remove config values")
flag.BoolVar(&removeFlag, "r", false, "remove config values")
err := flag.Parse(os.Args[1:])
if err != nil {
return err
}
if helpFlag {
flag.Usage()
return nil
}
if dumpFlag {
dumped := configMap.Flatten()
for k, v := range dumped {
fmt.Printf("%s=%s\n", k, v)
}
return nil
}
// Get the input string from the remaining command line arguments
input := flag.Args()
if len(input) == 0 {
flag.Usage()
return nil
}
var cErr error
noAssigns := inputWithoutAssigns(input)
if removeFlag {
cErr = removeInConfigJSON(configMap, input)
} else if noAssigns {
// print the values and return
return printValues(configMap, input)
} else {
cErr = insertInConfigJSON(configMap, input)
}
if cErr != nil {
return cErr
}
return configMap.SaveConfig()
}
func insertInConfigJSON(configMap ConfigMap, input []string) error {
// Parse the input string into key-value pairs
pairs, err := buildInputKVMap(input)
if err != nil {
return err
}
for k, v := range pairs {
if err := configMap.Insert(k, v); err != nil {
return err
}
}
return nil
}
func removeInConfigJSON(configMap ConfigMap, input []string) error {
for _, k := range input {
if err := configMap.Delete(k); err != nil {
return err
}
}
return nil
}
func inputWithoutAssigns(input []string) bool {
for _, arg := range input {
if strings.Contains(arg, "=") {
return false
}
}
return true
}
func printValues(configMap ConfigMap, keys []string) error {
for _, k := range keys {
val, err := configMap.Get(k)
if err != nil {
return err
}
fmt.Println(val)
}
return nil
}
type keyValues map[string]string
func (kv *keyValues) String() string {
return fmt.Sprintf("%v", *kv)
}
func (kv *keyValues) Set(value string) error {
parts := strings.SplitN(value, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("invalid key-value pair: %q", value)
}
key := parts[0]
val := parts[1]
if key == "" || val == "" {
return fmt.Errorf("invalid key-value pair: %q", value)
}
if *kv == nil {
*kv = make(keyValues)
}
(*kv)[key] = val
return nil
}
func buildInputKVMap(pairs []string) (keyValues, error) {
var kv keyValues
if len(pairs) == 0 {
return nil, fmt.Errorf("no key-value pairs provided")
}
for _, pair := range pairs {
if err := kv.Set(pair); err != nil {
return nil, err
}
}
return kv, nil
}