mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
Add env variables to configuration APIs output (#15465)
Config export and config get APIs now include environment variables set on the server
This commit is contained in:
parent
f4af2d3cdc
commit
3d94c38ec4
@ -189,15 +189,20 @@ func (a adminAPIHandlers) GetConfigKVHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
|
|
||||||
cfg := globalServerConfig.Clone()
|
cfg := globalServerConfig.Clone()
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
buf := &bytes.Buffer{}
|
subSys := vars["key"]
|
||||||
cw := config.NewConfigWriteTo(cfg, vars["key"])
|
subSysConfigs, err := cfg.GetSubsysInfo(subSys)
|
||||||
if _, err := cw.WriteTo(buf); err != nil {
|
if err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var s strings.Builder
|
||||||
|
for _, subSysConfig := range subSysConfigs {
|
||||||
|
subSysConfig.AddString(&s, false)
|
||||||
|
}
|
||||||
|
|
||||||
password := cred.SecretKey
|
password := cred.SecretKey
|
||||||
econfigData, err := madmin.EncryptData(password, buf.Bytes())
|
econfigData, err := madmin.EncryptData(password, []byte(s.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -427,42 +432,30 @@ func (a adminAPIHandlers) GetConfigHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
count += len(cfg[hkv.Key])
|
count += len(cfg[hkv.Key])
|
||||||
}
|
}
|
||||||
for _, hkv := range hkvs {
|
for _, hkv := range hkvs {
|
||||||
v := cfg[hkv.Key]
|
// We ignore the error below, as we cannot get one.
|
||||||
for target, kv := range v {
|
cfgSubsysItems, _ := cfg.GetSubsysInfo(hkv.Key)
|
||||||
off := kv.Get(config.Enable) == config.EnableOff
|
|
||||||
|
for _, item := range cfgSubsysItems {
|
||||||
|
off := item.Params.Get(config.Enable) == config.EnableOff
|
||||||
switch hkv.Key {
|
switch hkv.Key {
|
||||||
case config.EtcdSubSys:
|
case config.EtcdSubSys:
|
||||||
off = !etcd.Enabled(kv)
|
off = !etcd.Enabled(item.Params)
|
||||||
case config.CacheSubSys:
|
case config.CacheSubSys:
|
||||||
off = !cache.Enabled(kv)
|
off = !cache.Enabled(item.Params)
|
||||||
case config.StorageClassSubSys:
|
case config.StorageClassSubSys:
|
||||||
off = !storageclass.Enabled(kv)
|
off = !storageclass.Enabled(item.Params)
|
||||||
case config.PolicyPluginSubSys:
|
case config.PolicyPluginSubSys:
|
||||||
off = !polplugin.Enabled(kv)
|
off = !polplugin.Enabled(item.Params)
|
||||||
case config.IdentityOpenIDSubSys:
|
case config.IdentityOpenIDSubSys:
|
||||||
off = !openid.Enabled(kv)
|
off = !openid.Enabled(item.Params)
|
||||||
case config.IdentityLDAPSubSys:
|
case config.IdentityLDAPSubSys:
|
||||||
off = !xldap.Enabled(kv)
|
off = !xldap.Enabled(item.Params)
|
||||||
case config.IdentityTLSSubSys:
|
case config.IdentityTLSSubSys:
|
||||||
off = !globalSTSTLSConfig.Enabled
|
off = !globalSTSTLSConfig.Enabled
|
||||||
case config.IdentityPluginSubSys:
|
case config.IdentityPluginSubSys:
|
||||||
off = !idplugin.Enabled(kv)
|
off = !idplugin.Enabled(item.Params)
|
||||||
}
|
|
||||||
if off {
|
|
||||||
s.WriteString(config.KvComment)
|
|
||||||
s.WriteString(config.KvSpaceSeparator)
|
|
||||||
}
|
|
||||||
s.WriteString(hkv.Key)
|
|
||||||
if target != config.Default {
|
|
||||||
s.WriteString(config.SubSystemSeparator)
|
|
||||||
s.WriteString(target)
|
|
||||||
}
|
|
||||||
s.WriteString(config.KvSpaceSeparator)
|
|
||||||
s.WriteString(kv.String())
|
|
||||||
count--
|
|
||||||
if count > 0 {
|
|
||||||
s.WriteString(config.KvNewline)
|
|
||||||
}
|
}
|
||||||
|
item.AddString(&s, off)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,8 +508,7 @@ func parsEnvEntry(envEntry string) (envKV, error) {
|
|||||||
Skip: true,
|
Skip: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
const envSeparator = "="
|
envTokens := strings.SplitN(strings.TrimSpace(strings.TrimPrefix(envEntry, "export")), config.EnvSeparator, 2)
|
||||||
envTokens := strings.SplitN(strings.TrimSpace(strings.TrimPrefix(envEntry, "export")), envSeparator, 2)
|
|
||||||
if len(envTokens) != 2 {
|
if len(envTokens) != 2 {
|
||||||
return envKV{}, fmt.Errorf("envEntry malformed; %s, expected to be of form 'KEY=value'", envEntry)
|
return envKV{}, fmt.Errorf("envEntry malformed; %s, expected to be of form 'KEY=value'", envEntry)
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/minio/madmin-go"
|
"github.com/minio/madmin-go"
|
||||||
@ -51,6 +52,8 @@ const (
|
|||||||
Enable = madmin.EnableKey
|
Enable = madmin.EnableKey
|
||||||
Comment = madmin.CommentKey
|
Comment = madmin.CommentKey
|
||||||
|
|
||||||
|
EnvSeparator = "="
|
||||||
|
|
||||||
// Enable values
|
// Enable values
|
||||||
EnableOn = madmin.EnableOn
|
EnableOn = madmin.EnableOn
|
||||||
EnableOff = madmin.EnableOff
|
EnableOff = madmin.EnableOff
|
||||||
@ -1020,7 +1023,8 @@ func (c Config) CheckValidKeys(subSys string, deprecatedKeys []string) error {
|
|||||||
// GetAvailableTargets - returns a list of targets configured for the given
|
// GetAvailableTargets - returns a list of targets configured for the given
|
||||||
// subsystem (whether they are enabled or not). A target could be configured via
|
// subsystem (whether they are enabled or not). A target could be configured via
|
||||||
// environment variables or via the configuration store. The default target is
|
// environment variables or via the configuration store. The default target is
|
||||||
// `_` and is always returned.
|
// `_` and is always returned. The result is sorted so that the default target
|
||||||
|
// is the first one and the remaining entries are sorted in ascending order.
|
||||||
func (c Config) GetAvailableTargets(subSys string) ([]string, error) {
|
func (c Config) GetAvailableTargets(subSys string) ([]string, error) {
|
||||||
if SubSystemsSingleTargets.Contains(subSys) {
|
if SubSystemsSingleTargets.Contains(subSys) {
|
||||||
return []string{Default}, nil
|
return []string{Default}, nil
|
||||||
@ -1032,11 +1036,11 @@ func (c Config) GetAvailableTargets(subSys string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kvsMap := c[subSys]
|
kvsMap := c[subSys]
|
||||||
s := set.NewStringSet()
|
seen := set.NewStringSet()
|
||||||
|
|
||||||
// Add all targets that are configured in the config store.
|
// Add all targets that are configured in the config store.
|
||||||
for k := range kvsMap {
|
for k := range kvsMap {
|
||||||
s.Add(k)
|
seen.Add(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add targets that are configured via environment variables.
|
// Add targets that are configured via environment variables.
|
||||||
@ -1046,12 +1050,17 @@ func (c Config) GetAvailableTargets(subSys string) ([]string, error) {
|
|||||||
for _, k := range envsWithPrefix {
|
for _, k := range envsWithPrefix {
|
||||||
tgtName := strings.TrimPrefix(k, envVarPrefix)
|
tgtName := strings.TrimPrefix(k, envVarPrefix)
|
||||||
if tgtName != "" {
|
if tgtName != "" {
|
||||||
s.Add(tgtName)
|
seen.Add(tgtName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.ToSlice(), nil
|
seen.Remove(Default)
|
||||||
|
targets := seen.ToSlice()
|
||||||
|
sort.Strings(targets)
|
||||||
|
targets = append([]string{Default}, targets...)
|
||||||
|
|
||||||
|
return targets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnvVarName(subSys, target, param string) string {
|
func getEnvVarName(subSys, target, param string) string {
|
||||||
@ -1059,7 +1068,8 @@ func getEnvVarName(subSys, target, param string) string {
|
|||||||
return fmt.Sprintf("%s%s%s%s", EnvPrefix, strings.ToUpper(subSys), Default, strings.ToUpper(param))
|
return fmt.Sprintf("%s%s%s%s", EnvPrefix, strings.ToUpper(subSys), Default, strings.ToUpper(param))
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s%s%s%s%s%s", EnvPrefix, strings.ToUpper(subSys), Default, strings.ToUpper(param), Default, target)
|
return fmt.Sprintf("%s%s%s%s%s%s", EnvPrefix, strings.ToUpper(subSys), Default, strings.ToUpper(param),
|
||||||
|
Default, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolvableSubsystems = set.CreateStringSet(IdentityOpenIDSubSys)
|
var resolvableSubsystems = set.CreateStringSet(IdentityOpenIDSubSys)
|
||||||
@ -1102,7 +1112,7 @@ func (c Config) ResolveConfigParam(subSys, target, cfgParam string) (value strin
|
|||||||
|
|
||||||
defValue, isFound := defKVS.Lookup(cfgParam)
|
defValue, isFound := defKVS.Lookup(cfgParam)
|
||||||
// Comments usually are absent from `defKVS`, so we handle it specially.
|
// Comments usually are absent from `defKVS`, so we handle it specially.
|
||||||
if cfgParam == Comment {
|
if !isFound && cfgParam == Comment {
|
||||||
defValue, isFound = "", true
|
defValue, isFound = "", true
|
||||||
}
|
}
|
||||||
if !isFound {
|
if !isFound {
|
||||||
@ -1190,3 +1200,107 @@ func (c Config) GetResolvedConfigParams(subSys, target string) ([]KVSrc, error)
|
|||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) getTargetKVS(subSys, target string) KVS {
|
||||||
|
store, ok := c[subSys]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return store[target]
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvPair represents an environment variable and its value.
|
||||||
|
type EnvPair struct {
|
||||||
|
Name, Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubsysInfo holds config info for a subsystem target.
|
||||||
|
type SubsysInfo struct {
|
||||||
|
SubSys, Target string
|
||||||
|
Params KVS
|
||||||
|
|
||||||
|
// map of config parameter name to EnvPair.
|
||||||
|
EnvMap map[string]EnvPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubsysInfo returns `SubsysInfo`s for all targets for the subsystem.
|
||||||
|
func (c Config) GetSubsysInfo(subSys string) ([]SubsysInfo, error) {
|
||||||
|
// Check if config param requested is valid.
|
||||||
|
defKVS1, ok := DefaultKVS[subSys]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unknown subsystem: %s", subSys)
|
||||||
|
}
|
||||||
|
|
||||||
|
targets, err := c.GetAvailableTargets(subSys)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `Comment` configuration variable is optional but is available to be
|
||||||
|
// set for all sub-systems. It is not present in the `DefaultKVS` map's
|
||||||
|
// values. To enable fetching a configured comment value from the
|
||||||
|
// environment we add it to the list of default keys for the subsystem.
|
||||||
|
defKVS := make([]KV, len(defKVS1), len(defKVS1)+1)
|
||||||
|
copy(defKVS, defKVS1)
|
||||||
|
defKVS = append(defKVS, KV{Key: Comment})
|
||||||
|
|
||||||
|
r := make([]SubsysInfo, 0, len(targets))
|
||||||
|
for _, target := range targets {
|
||||||
|
kvs := c.getTargetKVS(subSys, target)
|
||||||
|
cs := SubsysInfo{
|
||||||
|
SubSys: subSys,
|
||||||
|
Target: target,
|
||||||
|
Params: kvs,
|
||||||
|
EnvMap: make(map[string]EnvPair),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all env vars that are set.
|
||||||
|
for _, kv := range defKVS {
|
||||||
|
envName := getEnvVarName(subSys, target, kv.Key)
|
||||||
|
envPair := EnvPair{
|
||||||
|
Name: envName,
|
||||||
|
Value: env.Get(envName, ""),
|
||||||
|
}
|
||||||
|
if envPair.Value != "" {
|
||||||
|
cs.EnvMap[kv.Key] = envPair
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = append(r, cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnvString adds env vars to the given string builder.
|
||||||
|
func (cs *SubsysInfo) AddEnvString(b *strings.Builder) {
|
||||||
|
for _, v := range cs.Params {
|
||||||
|
if ep, ok := cs.EnvMap[v.Key]; ok {
|
||||||
|
b.WriteString(KvComment)
|
||||||
|
b.WriteString(KvSpaceSeparator)
|
||||||
|
b.WriteString(ep.Name)
|
||||||
|
b.WriteString(EnvSeparator)
|
||||||
|
b.WriteString(ep.Value)
|
||||||
|
b.WriteString(KvNewline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddString adds the string representation of the configuration to the given
|
||||||
|
// builder. When off is true, adds a comment character before the config system
|
||||||
|
// output.
|
||||||
|
func (cs *SubsysInfo) AddString(b *strings.Builder, off bool) {
|
||||||
|
cs.AddEnvString(b)
|
||||||
|
if off {
|
||||||
|
b.WriteString(KvComment)
|
||||||
|
b.WriteString(KvSpaceSeparator)
|
||||||
|
}
|
||||||
|
b.WriteString(cs.SubSys)
|
||||||
|
if cs.Target != Default {
|
||||||
|
b.WriteString(SubSystemSeparator)
|
||||||
|
b.WriteString(cs.Target)
|
||||||
|
}
|
||||||
|
b.WriteString(KvSpaceSeparator)
|
||||||
|
b.WriteString(cs.Params.String())
|
||||||
|
b.WriteString(KvNewline)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user