oss/lib/config_helper.go (195 lines of code) (raw):
package lib
import (
"fmt"
"os"
"strconv"
"strings"
configparser "github.com/alyu/configparser"
)
// sections in config file
const (
CREDSection string = "Credentials"
BucketEndpointSection string = "Bucket-Endpoint"
BucketCnameSection string = "Bucket-Cname"
AkServiceSection string = "AkService"
DefaultSection string = "Default"
)
// config items in section AKSerivce
const (
ItemEcsAk string = "ecsAk"
)
// config items in section Credentials
const (
ItemRamRoleArn string = "ramRoleArn"
ItemExternalId string = "externalId"
)
type configOption struct {
showNames []string
cfInteractive bool
reveal bool
helpChinese string
helpEnglish string
}
// CredOptionList is all options in Credentials section
var CredOptionList = []string{
OptionLanguage,
OptionEndpoint,
OptionAccessKeyID,
OptionAccessKeySecret,
OptionSTSToken,
OptionOutputDir,
OptionRamRoleArn,
OptionUserAgent,
}
// CredOptionMap allows alias name for options in Credentials section
// name, allow to show in screen
var CredOptionMap = map[string]configOption{
OptionLanguage: configOption{[]string{"language", "Language"}, false, true, "", ""},
OptionEndpoint: configOption{[]string{"endpoint", "host"}, true, true, "", ""},
OptionAccessKeyID: configOption{[]string{"accessKeyID", "accessKeyId", "AccessKeyID", "AccessKeyId", "access_key_id", "access_id", "accessid", "access-key-id", "access-id"}, true, false, "", ""},
OptionAccessKeySecret: configOption{[]string{"accessKeySecret", "AccessKeySecret", "access_key_secret", "access_key", "accesskey", "access-key-secret", "access-key"}, true, false, "", ""},
OptionSTSToken: configOption{[]string{"stsToken", "ststoken", "STSToken", "sts_token", "sts-token"}, true, false, "", ""},
OptionOutputDir: configOption{[]string{"outputDir", "output-dir", "output_dir", "output_directory"}, false, true, "ossutil生成的文件的输出目录, ", "the directory to store files generated by ossutil, "},
OptionMode: configOption{[]string{"mode", "Mode"}, false, false, "", ""},
OptionRamRoleArn: configOption{[]string{"ramRoleArn", "RamRoleArn", "ramrolearn", "ram_role_arn", "ram-role-arn"}, false, false, "", ""},
OptionRoleSessionName: configOption{[]string{"roleSessionName", "RoleSessionName", "rolesessionname", "role-session-name", "role_session_name"}, false, false, "", ""},
OptionExternalId: configOption{[]string{"externalID", "externalId", "externalid", "external-id", "external_id"}, false, false, "", ""},
OptionTokenTimeout: configOption{[]string{"tokenTimeOut", "tokenTimeout", "tokentimeout", "token_timeout", "token-timeout"}, false, false, "", ""},
OptionSTSRegion: configOption{[]string{"stsRegion", "stsregion", "sts-region", "sts_region"}, false, false, "", ""},
OptionECSRoleName: configOption{[]string{"ecsRoleName", "EcsRoleName", "ecsrolename", "ecs-role-name", "ecs_role_name"}, false, false, "", ""},
}
// DefaultOptionMap allows alias name for options in default section
// name, allow to show in screen
var DefaultOptionMap = map[string]configOption{
OptionUserAgent: configOption{[]string{"userAgent", "useragent", "user-agent", "user_agent"}, false, false, "", ""},
OptionLogLevel: configOption{[]string{"loglevel", "log-level", "log_level"}, false, false, "", ""},
OptionProxyHost: configOption{[]string{"proxyHost", "proxyhost", "proxy-host", "proxy_host"}, false, false, "", ""},
OptionProxyUser: configOption{[]string{"proxyUser", "proxyuser", "proxy-user", "proxy_user"}, false, false, "", ""},
OptionProxyPwd: configOption{[]string{"proxyPwd", "proxypwd", "proxy-pwd", "proxy_pwd"}, false, false, "", ""},
OptionReadTimeout: configOption{[]string{"readTimeOut", "readtimeout", "read-timeout", "read_timeout"}, false, false, "", ""},
OptionConnectTimeout: configOption{[]string{"connectTimeOut", "connectTimeout", "connecttimeout", "connect-timeout", "connect_timeout"}, false, false, "", ""},
OptionRetryTimes: configOption{[]string{"retryTimes", "retrytimes", "retry-times", "retry_times"}, false, false, "", ""},
}
// DecideConfigFile return the config file, if user not specified, return default one
func DecideConfigFile(configFile string) string {
if configFile == "" {
configFile = DefaultConfigFile
}
if len(configFile) >= 2 && strings.HasPrefix(configFile, "~"+string(os.PathSeparator)) {
homeDir := currentHomeDir()
if homeDir != "" {
configFile = strings.Replace(configFile, "~", homeDir, 1)
}
}
return configFile
}
// LoadConfig load the specified config file
func LoadConfig(configFile string) (OptionMapType, error) {
var configMap OptionMapType
var err error
configMap, err = readConfigFromFile(configFile)
if err != nil {
return nil, fmt.Errorf("Read config file error: %s, please try \"help config\" to set configuration or use \"--config-file\" option", err)
}
if err = checkConfig(configMap); err != nil {
return nil, err
}
return configMap, nil
}
func readConfigFromFile(configFile string) (OptionMapType, error) {
configFile = DecideConfigFile(configFile)
config, err := configparser.Read(configFile)
if err != nil {
return nil, err
}
configMap := OptionMapType{}
// get options in Default Section
defaultSection, err := config.Section(DefaultSection)
if err == nil {
defaultOptions := defaultSection.Options()
for name, option := range defaultOptions {
if opName, ok := getOptionNameByDefault(strings.TrimSpace(name)); ok {
configMap[strings.TrimSpace(opName)] = strings.TrimSpace(option)
}
}
}
// get options in cred section
credSection, err := config.Section(CREDSection)
if err != nil {
return nil, err
}
credOptions := credSection.Options()
//added
//configMap[CREDSection] = map[string]string{}
for name, option := range credOptions {
if opName, ok := getOptionNameByStr(strings.TrimSpace(name)); ok {
configMap[strings.TrimSpace(opName)] = strings.TrimSpace(option)
} else {
configMap[strings.TrimSpace(name)] = strings.TrimSpace(option)
}
}
// get options in pair sections
for _, sec := range []string{BucketEndpointSection, BucketCnameSection} {
if section, err := config.Section(sec); err == nil {
configMap[sec] = map[string]string{}
options := section.Options()
for bucket, host := range options {
(configMap[sec]).(map[string]string)[strings.TrimSpace(bucket)] = strings.TrimSpace(host)
}
}
}
// get options in AKService for user-defined GetAk
sec := AkServiceSection
if section, err := config.Section(sec); err == nil {
configMap[sec] = map[string]string{}
options := section.Options()
for ecsUrl, strUrl := range options {
(configMap[sec]).(map[string]string)[strings.TrimSpace(ecsUrl)] = strings.TrimSpace(strUrl)
}
}
return configMap, nil
}
// get loglevel from config file
func readLoglevelFromFile(configFile string) (string, error) {
configFile = DecideConfigFile(configFile)
config, err := configparser.Read(configFile)
if err != nil {
return "", err
}
sectionNameList := []string{CREDSection, DefaultSection}
logConfig := DefaultOptionMap[OptionLogLevel]
for _, sectionName := range sectionNameList {
section, err := config.Section(sectionName)
if err != nil {
continue
}
for _, name := range logConfig.showNames {
val := section.ValueOf(name)
if val != "" {
return val, nil
}
}
}
return "", nil
}
func getOptionNameByStr(name string) (string, bool) {
for optionName, option := range CredOptionMap {
for _, val := range option.showNames {
if strings.EqualFold(name, val) {
return optionName, true
}
}
}
return "", false
}
func getOptionNameByDefault(name string) (string, bool) {
for optionName, option := range DefaultOptionMap {
for _, val := range option.showNames {
if strings.EqualFold(name, val) {
return optionName, true
}
}
}
return "", false
}
func checkConfig(configMap OptionMapType) error {
for name, opval := range configMap {
if option, ok := OptionMap[name]; ok {
if option.optionType == OptionTypeInt64 {
if _, err := strconv.ParseInt(opval.(string), 10, 64); err != nil {
return fmt.Errorf("error value of option \"%s\", the value is: %s in config file, which needs int64 type", name, opval)
}
}
if option.optionType == OptionTypeAlternative {
vals := strings.Split(option.minVal, "/")
if FindPosCaseInsen(opval.(string), vals) == -1 {
return fmt.Errorf("error value of option \"%s\", the value is: %s in config file, which is not anyone of %s", name, opval, option.minVal)
}
}
}
}
return nil
}