mirror of https://github.com/minio/minio.git
				
				
				
			Add target parsing code for config (#9375)
This code is helper for mcs project
This commit is contained in:
		
							parent
							
								
									8bae956df6
								
							
						
					
					
						commit
						d92db198d1
					
				| 
						 | 
				
			
			@ -22,7 +22,6 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/minio/minio-go/v6/pkg/set"
 | 
			
		||||
| 
						 | 
				
			
			@ -580,33 +579,6 @@ func (c Config) Clone() Config {
 | 
			
		|||
	return cp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Converts an input string of form "k1=v1 k2=v2" into fields
 | 
			
		||||
// of ["k1=v1", "k2=v2"], the tokenization of each `k=v`
 | 
			
		||||
// happens with the right number of input keys, if keys
 | 
			
		||||
// input is empty returned value is empty slice as well.
 | 
			
		||||
func kvFields(input string, keys []string) []string {
 | 
			
		||||
	var valueIndexes []int
 | 
			
		||||
	for _, key := range keys {
 | 
			
		||||
		i := strings.Index(input, key+KvSeparator)
 | 
			
		||||
		if i == -1 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		valueIndexes = append(valueIndexes, i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Ints(valueIndexes)
 | 
			
		||||
	var fields = make([]string, len(valueIndexes))
 | 
			
		||||
	for i := range valueIndexes {
 | 
			
		||||
		j := i + 1
 | 
			
		||||
		if j < len(valueIndexes) {
 | 
			
		||||
			fields[i] = strings.TrimSpace(input[valueIndexes[i]:valueIndexes[j]])
 | 
			
		||||
		} else {
 | 
			
		||||
			fields[i] = strings.TrimSpace(input[valueIndexes[i]:])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetKVS - set specific key values per sub-system.
 | 
			
		||||
func (c Config) SetKVS(s string, defaultKVS map[string]KVS) error {
 | 
			
		||||
	if len(s) == 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -635,7 +607,7 @@ func (c Config) SetKVS(s string, defaultKVS map[string]KVS) error {
 | 
			
		|||
		tgt = subSystemValue[1]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fields := kvFields(inputs[1], defaultKVS[subSys].Keys())
 | 
			
		||||
	fields := madmin.KvFields(inputs[1], defaultKVS[subSys].Keys())
 | 
			
		||||
	if len(fields) == 0 {
 | 
			
		||||
		return Errorf("sub-system '%s' cannot have empty keys", subSys)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,8 @@ package config
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/minio/minio/pkg/madmin"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestKVFields(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +92,7 @@ func TestKVFields(t *testing.T) {
 | 
			
		|||
	for _, test := range tests {
 | 
			
		||||
		test := test
 | 
			
		||||
		t.Run("", func(t *testing.T) {
 | 
			
		||||
			gotFields := kvFields(test.input, test.keys)
 | 
			
		||||
			gotFields := madmin.KvFields(test.input, test.keys)
 | 
			
		||||
			if len(gotFields) != len(test.expectedFields) {
 | 
			
		||||
				t.Errorf("Expected keys %d, found %d", len(test.expectedFields), len(gotFields))
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,15 @@ type HelpKV struct {
 | 
			
		|||
// HelpKVS - implement order of keys help messages.
 | 
			
		||||
type HelpKVS []HelpKV
 | 
			
		||||
 | 
			
		||||
// Keys returns help keys
 | 
			
		||||
func (h Help) Keys() []string {
 | 
			
		||||
	var keys []string
 | 
			
		||||
	for _, kh := range h.KeysHelp {
 | 
			
		||||
		keys = append(keys, kh.Key)
 | 
			
		||||
	}
 | 
			
		||||
	return keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HelpConfigKV - return help for a given sub-system.
 | 
			
		||||
func (adm *AdminClient) HelpConfigKV(ctx context.Context, subSys, key string, envOnly bool) (Help, error) {
 | 
			
		||||
	v := url.Values{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,71 @@
 | 
			
		|||
package madmin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"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"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Standard config keys and values.
 | 
			
		||||
const (
 | 
			
		||||
	EnableKey  = "enable"
 | 
			
		||||
| 
						 | 
				
			
			@ -60,3 +121,84 @@ func SanitizeValue(v string) string {
 | 
			
		|||
	v = strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(v), KvDoubleQuote), KvDoubleQuote)
 | 
			
		||||
	return strings.TrimSuffix(strings.TrimPrefix(v, KvSingleQuote), KvSingleQuote)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// KvFields - converts an input string of form "k1=v1 k2=v2" into
 | 
			
		||||
// fields of ["k1=v1", "k2=v2"], the tokenization of each `k=v`
 | 
			
		||||
// happens with the right number of input keys, if keys
 | 
			
		||||
// input is empty returned value is empty slice as well.
 | 
			
		||||
func KvFields(input string, keys []string) []string {
 | 
			
		||||
	var valueIndexes []int
 | 
			
		||||
	for _, key := range keys {
 | 
			
		||||
		i := strings.Index(input, key+KvSeparator)
 | 
			
		||||
		if i == -1 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		valueIndexes = append(valueIndexes, i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Ints(valueIndexes)
 | 
			
		||||
	var fields = make([]string, len(valueIndexes))
 | 
			
		||||
	for i := range valueIndexes {
 | 
			
		||||
		j := i + 1
 | 
			
		||||
		if j < len(valueIndexes) {
 | 
			
		||||
			fields[i] = strings.TrimSpace(input[valueIndexes[i]:valueIndexes[j]])
 | 
			
		||||
		} else {
 | 
			
		||||
			fields[i] = strings.TrimSpace(input[valueIndexes[i]:])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseTarget - adds new targets, by parsing the input string s.
 | 
			
		||||
func ParseTarget(s string, help Help) (*Target, error) {
 | 
			
		||||
	inputs := strings.SplitN(s, KvSpaceSeparator, 2)
 | 
			
		||||
	if len(inputs) <= 1 {
 | 
			
		||||
		return nil, fmt.Errorf("invalid number of arguments '%s'", s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	subSystemValue := strings.SplitN(inputs[0], SubSystemSeparator, 2)
 | 
			
		||||
	if len(subSystemValue) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("invalid number of arguments %s", s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if help.SubSys != subSystemValue[0] {
 | 
			
		||||
		return nil, fmt.Errorf("unknown sub-system %s", subSystemValue[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var kvs = KVS{}
 | 
			
		||||
	var prevK string
 | 
			
		||||
	for _, v := range KvFields(inputs[1], help.Keys()) {
 | 
			
		||||
		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 nil, fmt.Errorf("value for key '%s' cannot be empty", kv[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Target{
 | 
			
		||||
		SubSystem: inputs[0],
 | 
			
		||||
		KVS:       kvs,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseSubSysTarget - parse a sub-system target
 | 
			
		||||
func ParseSubSysTarget(buf []byte, help Help) (target *Target, err error) {
 | 
			
		||||
	bio := bufio.NewScanner(bytes.NewReader(buf))
 | 
			
		||||
	if bio.Scan() {
 | 
			
		||||
		return ParseTarget(bio.Text(), help)
 | 
			
		||||
	}
 | 
			
		||||
	return nil, bio.Err()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue