add comments
This commit is contained in:
parent
e7703f94bf
commit
4bf6f65377
45
cli/cli.go
45
cli/cli.go
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 cli
|
||||
|
||||
import (
|
||||
@ -11,10 +26,13 @@ import (
|
||||
"github.com/eschao/config/utils"
|
||||
)
|
||||
|
||||
// anyValue wraps a reflect.Value object and implements flag.Value interface
|
||||
// the reflect.Value could be Bool, String, Int, Uint and Float
|
||||
type anyValue struct {
|
||||
any reflect.Value
|
||||
}
|
||||
|
||||
// newAnyValue creates an anyValue object
|
||||
func newAnyValue(v reflect.Value) *anyValue {
|
||||
return &anyValue{any: v}
|
||||
}
|
||||
@ -78,6 +96,8 @@ func (this *anyValue) Set(v string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// sliceValue wraps a reflect.Value object and implements flag.Value interface
|
||||
// the reflect.Value could only be a sliceable type
|
||||
type sliceValue struct {
|
||||
value reflect.Value
|
||||
separator string
|
||||
@ -99,19 +119,26 @@ func (this *sliceValue) Set(v string) error {
|
||||
return utils.SetValueWithSlice(this.value, v, sp)
|
||||
}
|
||||
|
||||
// errorHanling is a global flag.ErrorHandling
|
||||
var errorHandling = flag.ExitOnError
|
||||
|
||||
// UsageFunc defines a callback function for printing command usage
|
||||
type UsageFunc func(*Command) func()
|
||||
|
||||
// usageHandler is a global UsageFunc callback, default is nil which means it
|
||||
// will use default flag.Usage function
|
||||
var usageHandler UsageFunc = nil
|
||||
|
||||
// Command defines a command line structure
|
||||
type Command struct {
|
||||
Name string
|
||||
FlagSet *flag.FlagSet
|
||||
Usage string
|
||||
SubCommands map[string]*Command
|
||||
Name string // command name
|
||||
FlagSet *flag.FlagSet // command arguments
|
||||
Usage string // command usage description
|
||||
SubCommands map[string]*Command // sub-commands
|
||||
}
|
||||
|
||||
// New creates a command with given name, the command will use default
|
||||
// ErrorHandling: flag.ExitOnError and default usage function: flag.Usage
|
||||
func New(name string) *Command {
|
||||
cmd := Command{
|
||||
Name: name,
|
||||
@ -122,6 +149,8 @@ func New(name string) *Command {
|
||||
return &cmd
|
||||
}
|
||||
|
||||
// NewWith creates a command with given name, error handling and customized
|
||||
// usage function
|
||||
func NewWith(name string, errHandling flag.ErrorHandling,
|
||||
usageHandling UsageFunc) *Command {
|
||||
errorHandling = errHandling
|
||||
@ -139,6 +168,9 @@ func NewWith(name string, errHandling flag.ErrorHandling,
|
||||
return &cmd
|
||||
}
|
||||
|
||||
// Init analyzes the given structure interface, extracts cli definitions from
|
||||
// its tag and installs command flagset by flag APIs. The interface must be a
|
||||
// structure pointer, otherwise will return an error
|
||||
func (this *Command) Init(i interface{}) error {
|
||||
ptrRef := reflect.ValueOf(i)
|
||||
|
||||
@ -156,6 +188,7 @@ func (this *Command) Init(i interface{}) error {
|
||||
return this.parseValue(valueOfStruct)
|
||||
}
|
||||
|
||||
// parseValue parses a reflect.Value object and extracts cli definitions
|
||||
func (this *Command) parseValue(v reflect.Value) error {
|
||||
typeOfStruct := v.Type()
|
||||
var err error
|
||||
@ -181,6 +214,7 @@ func (this *Command) parseValue(v reflect.Value) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// addFlag installs a command flag variable by flag API
|
||||
func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
|
||||
cmdTag, ok := f.Tag.Lookup("cli")
|
||||
if !ok || cmdTag == "" {
|
||||
@ -226,6 +260,7 @@ func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// createSubCommand creates sub-commands
|
||||
func (this *Command) createSubCommand(tag reflect.StructTag) *Command {
|
||||
cmdTag, ok := tag.Lookup("cli")
|
||||
if !ok || cmdTag == "" {
|
||||
@ -253,6 +288,8 @@ func (this *Command) createSubCommand(tag reflect.StructTag) *Command {
|
||||
return &cmd
|
||||
}
|
||||
|
||||
// Parse parses values from command line and save values into given structure.
|
||||
// The Init(interface{}) function must be called before parsing
|
||||
func (this *Command) Parse(args []string) error {
|
||||
if err := this.FlagSet.Parse(args); err != nil {
|
||||
return err
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 cli
|
||||
|
||||
import (
|
||||
|
39
config.go
39
config.go
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 (
|
||||
@ -15,6 +30,7 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Default configuration file
|
||||
const (
|
||||
DefaultJSONConfig = "config.json"
|
||||
DefaultYamlConfig = "config.yaml"
|
||||
@ -27,6 +43,10 @@ const (
|
||||
PropConfigType = "properties"
|
||||
)
|
||||
|
||||
// ParseDefault parses the given structure, extract default value from its tag
|
||||
// and set structure with these values.
|
||||
// Normally, ParseDefault should be called before any other parsing functions
|
||||
// to set default values for structure.
|
||||
func ParseDefault(i interface{}) error {
|
||||
ptrRef := reflect.ValueOf(i)
|
||||
|
||||
@ -108,10 +128,13 @@ func parseValue(v reflect.Value) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ParseEnv parses given structure interface and set it with corresponding
|
||||
// environment values
|
||||
func ParseEnv(i interface{}) error {
|
||||
return env.ParseWith(i, "")
|
||||
}
|
||||
|
||||
// ParseCli parses given structure interface and set it with command line input
|
||||
func ParseCli(i interface{}) error {
|
||||
cli := cli.New(os.Args[0])
|
||||
if err := cli.Init(i); err != nil {
|
||||
@ -123,11 +146,19 @@ func ParseCli(i interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseConfig parses given structure interface and set it with default
|
||||
// configuration file.
|
||||
// configFlag is a command line flag to tell where to locate configure file.
|
||||
// If the config file doesn't exist, the default config fill will be searched
|
||||
// under the same folder with the fixed order: config.json, config.yaml and
|
||||
// config.properties
|
||||
func ParseConfig(i interface{}, configFlag string) error {
|
||||
configFile := flag.String(configFlag, "", "Specifiy configuration file")
|
||||
return ParseConfigFile(i, *configFile)
|
||||
}
|
||||
|
||||
// ParseConfigFile parses given structure interface and set its value with
|
||||
// the specified configuration file
|
||||
func ParseConfigFile(i interface{}, configFile string) error {
|
||||
var err error
|
||||
if configFile == "" {
|
||||
@ -156,6 +187,7 @@ func ParseConfigFile(i interface{}, configFile string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseJSON parses JSON file and set structure with its value
|
||||
func parseJSON(i interface{}, jsonFile string) error {
|
||||
raw, err := ioutil.ReadFile(jsonFile)
|
||||
if err != nil {
|
||||
@ -165,6 +197,7 @@ func parseJSON(i interface{}, jsonFile string) error {
|
||||
return json.Unmarshal(raw, i)
|
||||
}
|
||||
|
||||
// parseYaml parses Yaml file and set structure with its value
|
||||
func parseYaml(i interface{}, yamlFile string) error {
|
||||
raw, err := ioutil.ReadFile(yamlFile)
|
||||
if err != nil {
|
||||
@ -174,10 +207,14 @@ func parseYaml(i interface{}, yamlFile string) error {
|
||||
return yaml.Unmarshal(raw, i)
|
||||
}
|
||||
|
||||
// parseProp parses Properties file and set structure with its value
|
||||
func parseProp(i interface{}, propFile string) error {
|
||||
return fmt.Errorf("Properties config has not implemented!")
|
||||
}
|
||||
|
||||
// getDefaultConfigFile returns a existing default config file. The checking
|
||||
// order is fixed with beginning from: config.json to config.yaml and
|
||||
// config.properties
|
||||
func getDefaultConfigFile() (string, error) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
@ -207,6 +244,8 @@ func getDefaultConfigFile() (string, error) {
|
||||
return "", fmt.Errorf("No default config file found in path: %s", path)
|
||||
}
|
||||
|
||||
// getConfigFileType analyzes config file extension name and return
|
||||
// corresponding type: json, yaml or properties
|
||||
func getConfigFileType(configFile string) (string, error) {
|
||||
ext := filepath.Ext(configFile)
|
||||
if ext == ".json" {
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 (
|
||||
|
33
env/env.go
vendored
33
env/env.go
vendored
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 env
|
||||
|
||||
import (
|
||||
@ -8,10 +23,25 @@ import (
|
||||
"github.com/eschao/config/utils"
|
||||
)
|
||||
|
||||
// Parse parses given structure interface, extracts environment definitions
|
||||
// from its tag and sets structure with defined environement variables
|
||||
func Parse(i interface{}) error {
|
||||
return ParseWith(i, "")
|
||||
}
|
||||
|
||||
// ParseWith parses with given structure interface and environment name prefix
|
||||
// It is normally used in nested structure.
|
||||
// For example: we have such structure
|
||||
// type Database struct {
|
||||
// Host string `env:"HOST"`
|
||||
// }
|
||||
|
||||
// type Server struct {
|
||||
// Server string `env:"SERVER"`
|
||||
// DB Database `env:"DB_"`
|
||||
// }
|
||||
// The Server.DB.Host will be mapped to environment variable: DB_HOST which is
|
||||
// concatenated from DB tag in Server struct and Host tag in Database struct
|
||||
func ParseWith(i interface{}, prefix string) error {
|
||||
ptrRef := reflect.ValueOf(i)
|
||||
|
||||
@ -29,6 +59,7 @@ func ParseWith(i interface{}, prefix string) error {
|
||||
return parseValue(valueOfStruct, prefix)
|
||||
}
|
||||
|
||||
// parseValue parses a reflect.Value object
|
||||
func parseValue(v reflect.Value, prefix string) error {
|
||||
typeOfStruct := v.Type()
|
||||
var err error
|
||||
@ -55,6 +86,7 @@ func parseValue(v reflect.Value, prefix string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// getEnvValue get environment value
|
||||
func getEnvValue(envName string, f reflect.StructField) (string, bool) {
|
||||
//fmt.Printf("Lookup ENV: %s\n", envName)
|
||||
envValue, ok := os.LookupEnv(envName)
|
||||
@ -65,6 +97,7 @@ func getEnvValue(envName string, f reflect.StructField) (string, bool) {
|
||||
return envValue, ok
|
||||
}
|
||||
|
||||
// setFieldValue sets a reflect.Value with environment value
|
||||
func setFieldValue(v reflect.Value, f reflect.StructField, prefix string) error {
|
||||
envName := f.Tag.Get("env")
|
||||
if envName == "" {
|
||||
|
15
env/env_test.go
vendored
15
env/env_test.go
vendored
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 env
|
||||
|
||||
import (
|
||||
|
15
test/data.go
15
test/data.go
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 test
|
||||
|
||||
type DBConfig struct {
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 utils
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2017 eschao <esc.chao@gmail.com>
|
||||
*
|
||||
* Licensed 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 utils
|
||||
|
||||
import (
|
||||
|
Loading…
Reference in New Issue
Block a user