mirror of
https://github.com/minio/minio.git
synced 2025-11-09 13:39:46 -05:00
fix: config to support keys with special values (#9304)
This PR adds context-based `k=v` splits based on the sub-system which was obtained, if the keys are not provided an error will be thrown during parsing, if keys are provided with wrong values an error will be thrown. Keys can now have values which are of a much more complex form such as `k="v=v"` or `k=" v = v"` and other variations. additionally, deprecate unnecessary postgres/mysql configuration styles, support only - connection_string for Postgres - dsn_string for MySQL All other parameters are removed.
This commit is contained in:
@@ -78,7 +78,7 @@ func (adm *AdminClient) SetConfigKV(ctx context.Context, kv string) (err error)
|
||||
}
|
||||
|
||||
// GetConfigKV - returns the key, value of the requested key, incoming data is encrypted.
|
||||
func (adm *AdminClient) GetConfigKV(ctx context.Context, key string) (Targets, error) {
|
||||
func (adm *AdminClient) GetConfigKV(ctx context.Context, key string) ([]byte, error) {
|
||||
v := url.Values{}
|
||||
v.Set("key", key)
|
||||
|
||||
@@ -100,10 +100,5 @@ func (adm *AdminClient) GetConfigKV(ctx context.Context, key string) (Targets, e
|
||||
return nil, httpRespToErrorResponse(resp)
|
||||
}
|
||||
|
||||
data, err := DecryptData(adm.getSecretKey(), resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseSubSysTarget(data)
|
||||
return DecryptData(adm.getSecretKey(), resp.Body)
|
||||
}
|
||||
|
||||
@@ -18,73 +18,10 @@
|
||||
package madmin
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// KV - is a shorthand of each key value.
|
||||
type KV struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// KVS - is a shorthand for some wrapper functions
|
||||
// to operate on list of key values.
|
||||
type KVS []KV
|
||||
|
||||
// Empty - return if kv is empty
|
||||
func (kvs KVS) Empty() bool {
|
||||
return len(kvs) == 0
|
||||
}
|
||||
|
||||
// Set sets a value, if not sets a default value.
|
||||
func (kvs *KVS) Set(key, value string) {
|
||||
for i, kv := range *kvs {
|
||||
if kv.Key == key {
|
||||
(*kvs)[i] = KV{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
*kvs = append(*kvs, KV{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
|
||||
// Get - returns the value of a key, if not found returns empty.
|
||||
func (kvs KVS) Get(key string) string {
|
||||
v, ok := kvs.Lookup(key)
|
||||
if ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Lookup - lookup a key in a list of KVS
|
||||
func (kvs KVS) Lookup(key string) (string, bool) {
|
||||
for _, kv := range kvs {
|
||||
if kv.Key == key {
|
||||
return kv.Value, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Target signifies an individual target
|
||||
type Target struct {
|
||||
SubSystem string `json:"subSys"`
|
||||
KVS KVS `json:"kvs"`
|
||||
}
|
||||
|
||||
// Targets sub-system targets
|
||||
type Targets []Target
|
||||
|
||||
// Standard config keys and values.
|
||||
const (
|
||||
EnableKey = "enable"
|
||||
@@ -95,36 +32,6 @@ const (
|
||||
EnableOff = "off"
|
||||
)
|
||||
|
||||
func (kvs KVS) String() string {
|
||||
var s strings.Builder
|
||||
for _, kv := range kvs {
|
||||
// Do not need to print state which is on.
|
||||
if kv.Key == EnableKey && kv.Value == EnableOn {
|
||||
continue
|
||||
}
|
||||
if kv.Key == CommentKey && kv.Value == "" {
|
||||
continue
|
||||
}
|
||||
s.WriteString(kv.Key)
|
||||
s.WriteString(KvSeparator)
|
||||
spc := HasSpace(kv.Value)
|
||||
if spc {
|
||||
s.WriteString(KvDoubleQuote)
|
||||
}
|
||||
s.WriteString(kv.Value)
|
||||
if spc {
|
||||
s.WriteString(KvDoubleQuote)
|
||||
}
|
||||
s.WriteString(KvSpaceSeparator)
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Count - returns total numbers of target
|
||||
func (t Targets) Count() int {
|
||||
return len(t)
|
||||
}
|
||||
|
||||
// HasSpace - returns if given string has space.
|
||||
func HasSpace(s string) bool {
|
||||
for _, r := range s {
|
||||
@@ -135,23 +42,6 @@ func HasSpace(s string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t Targets) String() string {
|
||||
var s strings.Builder
|
||||
count := t.Count()
|
||||
// Print all "on" states entries
|
||||
for _, targetKV := range t {
|
||||
kv := targetKV.KVS
|
||||
count--
|
||||
s.WriteString(targetKV.SubSystem)
|
||||
s.WriteString(KvSpaceSeparator)
|
||||
s.WriteString(kv.String())
|
||||
if len(t) > 1 && count > 0 {
|
||||
s.WriteString(KvNewline)
|
||||
}
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Constant separators
|
||||
const (
|
||||
SubSystemSeparator = `:`
|
||||
@@ -170,69 +60,3 @@ func SanitizeValue(v string) string {
|
||||
v = strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(v), KvDoubleQuote), KvDoubleQuote)
|
||||
return strings.TrimSuffix(strings.TrimPrefix(v, KvSingleQuote), KvSingleQuote)
|
||||
}
|
||||
|
||||
// AddTarget - adds new targets, by parsing the input string s.
|
||||
func (t *Targets) AddTarget(s string) error {
|
||||
inputs := strings.SplitN(s, KvSpaceSeparator, 2)
|
||||
if len(inputs) <= 1 {
|
||||
return fmt.Errorf("invalid number of arguments '%s'", s)
|
||||
}
|
||||
|
||||
subSystemValue := strings.SplitN(inputs[0], SubSystemSeparator, 2)
|
||||
if len(subSystemValue) == 0 {
|
||||
return fmt.Errorf("invalid number of arguments %s", s)
|
||||
}
|
||||
|
||||
var kvs = KVS{}
|
||||
var prevK string
|
||||
for _, v := range strings.Fields(inputs[1]) {
|
||||
kv := strings.SplitN(v, KvSeparator, 2)
|
||||
if len(kv) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(kv) == 1 && prevK != "" {
|
||||
value := strings.Join([]string{
|
||||
kvs.Get(prevK),
|
||||
SanitizeValue(kv[0]),
|
||||
}, KvSpaceSeparator)
|
||||
kvs.Set(prevK, value)
|
||||
continue
|
||||
}
|
||||
if len(kv) == 2 {
|
||||
prevK = kv[0]
|
||||
kvs.Set(prevK, SanitizeValue(kv[1]))
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("value for key '%s' cannot be empty", kv[0])
|
||||
}
|
||||
|
||||
for i := range *t {
|
||||
if (*t)[i].SubSystem == inputs[0] {
|
||||
(*t)[i] = Target{
|
||||
SubSystem: inputs[0],
|
||||
KVS: kvs,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
*t = append(*t, Target{
|
||||
SubSystem: inputs[0],
|
||||
KVS: kvs,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseSubSysTarget - parse sub-system target
|
||||
func ParseSubSysTarget(buf []byte) (Targets, error) {
|
||||
var targets Targets
|
||||
bio := bufio.NewScanner(bytes.NewReader(buf))
|
||||
for bio.Scan() {
|
||||
if err := targets.AddTarget(bio.Text()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := bio.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return targets, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user