Выполнен рефакторинг. Добавлен workflow.
This commit is contained in:
parent
f884b56a10
commit
a06ee87fba
38
.gitea/workflows/test.yaml
Normal file
38
.gitea/workflows/test.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: test
|
||||||
|
run-name: ${{ gitea.actor }} test MouseSoft Config
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: check-out
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: set-up go
|
||||||
|
uses: https://gitea.com/actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ">=1.22"
|
||||||
|
|
||||||
|
- name: set-up dependencies
|
||||||
|
run: |
|
||||||
|
go install github.com/kisielk/errcheck@latest
|
||||||
|
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
go install github.com/sashamelentyev/usestdlibvars@latest
|
||||||
|
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest
|
||||||
|
make vendor
|
||||||
|
|
||||||
|
- name: lint
|
||||||
|
run: make lint
|
||||||
|
|
||||||
|
# - name: golangci-lint
|
||||||
|
# uses: https://github.com/golangci/golangci-lint-action@v6
|
||||||
|
# with:
|
||||||
|
# version: v1.60
|
||||||
|
|
||||||
|
- name: test
|
||||||
|
id: build
|
||||||
|
run: make test
|
314
.golangci.yaml
Normal file
314
.golangci.yaml
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
# This file contains all available configuration options
|
||||||
|
# with their default values (in comments).
|
||||||
|
#
|
||||||
|
# This file is not a configuration example,
|
||||||
|
# it contains the exhaustive configuration with explanations of the options.
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# Disable all linters.
|
||||||
|
# Default: false
|
||||||
|
disable-all: true
|
||||||
|
# Enable specific linter
|
||||||
|
# https://golangci-lint.run/usage/linters/#enabled-by-default
|
||||||
|
enable:
|
||||||
|
- asasalint
|
||||||
|
- asciicheck
|
||||||
|
- bidichk
|
||||||
|
- bodyclose
|
||||||
|
- canonicalheader
|
||||||
|
- containedctx
|
||||||
|
- contextcheck
|
||||||
|
- copyloopvar
|
||||||
|
- cyclop
|
||||||
|
- decorder
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- dupword
|
||||||
|
- durationcheck
|
||||||
|
- err113
|
||||||
|
- errcheck
|
||||||
|
- errchkjson
|
||||||
|
- errname
|
||||||
|
- errorlint
|
||||||
|
- exhaustive
|
||||||
|
- fatcontext
|
||||||
|
- forcetypeassert
|
||||||
|
- funlen
|
||||||
|
- gci
|
||||||
|
- ginkgolinter
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- gochecksumtype
|
||||||
|
- gocognit
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goheader
|
||||||
|
- goimports
|
||||||
|
- gomoddirectives
|
||||||
|
- gomodguard
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- gosmopolitan
|
||||||
|
- govet
|
||||||
|
- grouper
|
||||||
|
- importas
|
||||||
|
- inamedparam
|
||||||
|
- ineffassign
|
||||||
|
- interfacebloat
|
||||||
|
- intrange
|
||||||
|
- ireturn
|
||||||
|
- lll
|
||||||
|
- loggercheck
|
||||||
|
- maintidx
|
||||||
|
- makezero
|
||||||
|
- mirror
|
||||||
|
- misspell
|
||||||
|
- mnd
|
||||||
|
- musttag
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- nilerr
|
||||||
|
- nilnil
|
||||||
|
- nlreturn
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- nonamedreturns
|
||||||
|
- nosprintfhostport
|
||||||
|
- paralleltest
|
||||||
|
- perfsprint
|
||||||
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- promlinter
|
||||||
|
- protogetter
|
||||||
|
- reassign
|
||||||
|
- revive
|
||||||
|
- rowserrcheck
|
||||||
|
- sloglint
|
||||||
|
- spancheck
|
||||||
|
- sqlclosecheck
|
||||||
|
- staticcheck
|
||||||
|
- stylecheck
|
||||||
|
- tagalign
|
||||||
|
- tagliatelle
|
||||||
|
- tenv
|
||||||
|
- testableexamples
|
||||||
|
- testifylint
|
||||||
|
- testpackage
|
||||||
|
- thelper
|
||||||
|
- tparallel
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- usestdlibvars
|
||||||
|
- varnamelen
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
- wrapcheck
|
||||||
|
- wsl
|
||||||
|
- zerologlint
|
||||||
|
|
||||||
|
# Enable all available linters.
|
||||||
|
# Default: false
|
||||||
|
enable-all: false
|
||||||
|
|
||||||
|
# Enable only fast linters from enabled linters set (first run won't be fast)
|
||||||
|
# Default: false
|
||||||
|
fast: true
|
||||||
|
|
||||||
|
# All available settings of specific linters.
|
||||||
|
linters-settings:
|
||||||
|
cyclop:
|
||||||
|
# The maximal code complexity to report.
|
||||||
|
# Default: 10
|
||||||
|
max-complexity: 20
|
||||||
|
# Should ignore tests.
|
||||||
|
# Default: false
|
||||||
|
skip-tests: true
|
||||||
|
|
||||||
|
funlen:
|
||||||
|
# Checks the number of lines in a function.
|
||||||
|
# If lower than 0, disable the check.
|
||||||
|
# Default: 60
|
||||||
|
lines: 80
|
||||||
|
# Checks the number of statements in a function.
|
||||||
|
# If lower than 0, disable the check.
|
||||||
|
# Default: 40
|
||||||
|
statements: 50
|
||||||
|
# Ignore comments when counting lines.
|
||||||
|
# Default false
|
||||||
|
ignore-comments: true
|
||||||
|
|
||||||
|
gocognit:
|
||||||
|
# Minimal code complexity to report.
|
||||||
|
# Default: 30 (but we recommend 10-20)
|
||||||
|
min-complexity: 20
|
||||||
|
|
||||||
|
gocyclo:
|
||||||
|
# Minimal code complexity to report.
|
||||||
|
# Default: 30 (but we recommend 10-20)
|
||||||
|
min-complexity: 20
|
||||||
|
|
||||||
|
godot:
|
||||||
|
# Comments to be checked: `declarations`, `toplevel`, or `all`.
|
||||||
|
# Default: declarations
|
||||||
|
scope: all
|
||||||
|
# List of regexps for excluding particular comment lines from check.
|
||||||
|
# Default: []
|
||||||
|
exclude:
|
||||||
|
# Exclude todo and fixme comments.
|
||||||
|
- "^fixme:"
|
||||||
|
- "^todo:"
|
||||||
|
# Check that each sentence ends with a period.
|
||||||
|
# Default: true
|
||||||
|
period: false
|
||||||
|
# Check that each sentence starts with a capital letter.
|
||||||
|
# Default: false
|
||||||
|
capital: true
|
||||||
|
|
||||||
|
goimports:
|
||||||
|
local-prefixes: git.mousesoft.ru/ms/config
|
||||||
|
|
||||||
|
gosec:
|
||||||
|
excludes:
|
||||||
|
- G115
|
||||||
|
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
- name: unexported-return
|
||||||
|
disabled: true
|
||||||
|
|
||||||
|
# output configuration options
|
||||||
|
output:
|
||||||
|
# The formats used to render issues.
|
||||||
|
# Formats:
|
||||||
|
# - `colored-line-number`
|
||||||
|
# - `line-number`
|
||||||
|
# - `json`
|
||||||
|
# - `colored-tab`
|
||||||
|
# - `tab`
|
||||||
|
# - `html`
|
||||||
|
# - `checkstyle`
|
||||||
|
# - `code-climate`
|
||||||
|
# - `junit-xml`
|
||||||
|
# - `junit-xml-extended`
|
||||||
|
# - `github-actions`
|
||||||
|
# - `teamcity`
|
||||||
|
# - `sarif`
|
||||||
|
# Output path can be either `stdout`, `stderr` or path to the file to write to.
|
||||||
|
#
|
||||||
|
# For the CLI flag (`--out-format`), multiple formats can be specified by separating them by comma.
|
||||||
|
# The output can be specified for each of them by separating format name and path by colon symbol.
|
||||||
|
# Example: "--out-format=checkstyle:report.xml,json:stdout,colored-line-number"
|
||||||
|
# The CLI flag (`--out-format`) override the configuration file.
|
||||||
|
#
|
||||||
|
# Default:
|
||||||
|
# formats:
|
||||||
|
# - format: colored-line-number
|
||||||
|
# path: stdout
|
||||||
|
formats:
|
||||||
|
# - format: json
|
||||||
|
# path: stderr
|
||||||
|
# - format: checkstyle
|
||||||
|
# path: report.xml
|
||||||
|
- format: colored-line-number
|
||||||
|
|
||||||
|
# Print lines of code with issue.
|
||||||
|
# Default: true
|
||||||
|
print-issued-lines: false
|
||||||
|
|
||||||
|
# Print linter name in the end of issue text.
|
||||||
|
# Default: true
|
||||||
|
print-linter-name: true
|
||||||
|
|
||||||
|
# Make issues output unique by line.
|
||||||
|
# Default: true
|
||||||
|
uniq-by-line: false
|
||||||
|
|
||||||
|
# Add a prefix to the output file references.
|
||||||
|
# Default: ""
|
||||||
|
path-prefix: ""
|
||||||
|
|
||||||
|
# Sort results by the order defined in `sort-order`.
|
||||||
|
# Default: false
|
||||||
|
sort-results: true
|
||||||
|
|
||||||
|
# Order to use when sorting results.
|
||||||
|
# Require `sort-results` to `true`.
|
||||||
|
# Possible values: `file`, `linter`, and `severity`.
|
||||||
|
#
|
||||||
|
# If the severity values are inside the following list, they are ordered in this order:
|
||||||
|
# 1. error
|
||||||
|
# 2. warning
|
||||||
|
# 3. high
|
||||||
|
# 4. medium
|
||||||
|
# 5. low
|
||||||
|
# Either they are sorted alphabetically.
|
||||||
|
#
|
||||||
|
# Default: ["file"]
|
||||||
|
sort-order:
|
||||||
|
- linter
|
||||||
|
- severity
|
||||||
|
- file # filepath, line, and column.
|
||||||
|
|
||||||
|
# Show statistics per linter.
|
||||||
|
# Default: false
|
||||||
|
show-stats: true
|
||||||
|
|
||||||
|
# Options for analysis running.
|
||||||
|
run:
|
||||||
|
# Timeout for analysis, e.g. 30s, 5m.
|
||||||
|
# Default: 1m
|
||||||
|
timeout: 5m
|
||||||
|
|
||||||
|
# Exit code when at least one issue was found.
|
||||||
|
# Default: 1
|
||||||
|
issues-exit-code: 2
|
||||||
|
|
||||||
|
# Include test files or not.
|
||||||
|
# Default: true
|
||||||
|
tests: false
|
||||||
|
|
||||||
|
# List of build tags, all linters use it.
|
||||||
|
# Default: []
|
||||||
|
build-tags:
|
||||||
|
- mytag
|
||||||
|
|
||||||
|
# If set, we pass it to "go list -mod={option}". From "go help modules":
|
||||||
|
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
||||||
|
# automatic updating of go.mod described above. Instead, it fails when any changes
|
||||||
|
# to go.mod are needed. This setting is most useful to check that go.mod does
|
||||||
|
# not need updates, such as in a continuous integration and testing system.
|
||||||
|
# If invoked with -mod=vendor, the go command assumes that the vendor
|
||||||
|
# directory holds the correct copies of dependencies and ignores
|
||||||
|
# the dependency descriptions in go.mod.
|
||||||
|
#
|
||||||
|
# Allowed values: readonly|vendor|mod
|
||||||
|
# Default: ""
|
||||||
|
modules-download-mode: readonly
|
||||||
|
|
||||||
|
# Allow multiple parallel golangci-lint instances running.
|
||||||
|
# If false, golangci-lint acquires file lock on start.
|
||||||
|
# Default: false
|
||||||
|
allow-parallel-runners: true
|
||||||
|
|
||||||
|
# Allow multiple golangci-lint instances running, but serialize them around a lock.
|
||||||
|
# If false, golangci-lint exits with an error if it fails to acquire file lock on start.
|
||||||
|
# Default: false
|
||||||
|
allow-serial-runners: true
|
||||||
|
|
||||||
|
# Define the Go version limit.
|
||||||
|
# Mainly related to generics support since go1.18.
|
||||||
|
# Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17
|
||||||
|
go: "1.22"
|
||||||
|
|
||||||
|
# Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously.
|
||||||
|
# If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota.
|
||||||
|
# Default: the number of logical CPUs in the machine
|
||||||
|
concurrency: 4
|
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@ -1,8 +1,16 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"errcheck",
|
||||||
"eschao",
|
"eschao",
|
||||||
|
"gitea",
|
||||||
|
"golangci",
|
||||||
"gopkg",
|
"gopkg",
|
||||||
|
"honnef",
|
||||||
|
"kisielk",
|
||||||
|
"sashamelentyev",
|
||||||
|
"staticcheck",
|
||||||
"stretchr",
|
"stretchr",
|
||||||
"struct"
|
"struct",
|
||||||
|
"usestdlibvars"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package cli
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
@ -22,8 +22,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"git.mousesoft.ru/ms/config/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// anyValue wraps a reflect.Value object and implements flag.Value interface
|
// anyValue wraps a reflect.Value object and implements flag.Value interface
|
||||||
@ -70,25 +68,25 @@ func (av *anyValue) Set(v string) error {
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
av.any.SetString(v)
|
av.any.SetString(v)
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
return utils.SetValueWithFloatX(av.any, v, 32)
|
return SetValueWithFloatX(av.any, v, 32)
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
return utils.SetValueWithFloatX(av.any, v, 64)
|
return SetValueWithFloatX(av.any, v, 64)
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
return utils.SetValueWithIntX(av.any, v, 8)
|
return SetValueWithIntX(av.any, v, 8)
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
return utils.SetValueWithIntX(av.any, v, 16)
|
return SetValueWithIntX(av.any, v, 16)
|
||||||
case reflect.Int, reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
return utils.SetValueWithIntX(av.any, v, 32)
|
return SetValueWithIntX(av.any, v, 32)
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return utils.SetValueWithIntX(av.any, v, 64)
|
return SetValueWithIntX(av.any, v, 64)
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
return utils.SetValueWithUintX(av.any, v, 8)
|
return SetValueWithUintX(av.any, v, 8)
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
return utils.SetValueWithUintX(av.any, v, 16)
|
return SetValueWithUintX(av.any, v, 16)
|
||||||
case reflect.Uint, reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
return utils.SetValueWithUintX(av.any, v, 32)
|
return SetValueWithUintX(av.any, v, 32)
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return utils.SetValueWithUintX(av.any, v, 64)
|
return SetValueWithUintX(av.any, v, 64)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type: %s", kind.String())
|
return fmt.Errorf("unsupported type: %s", kind.String())
|
||||||
}
|
}
|
||||||
@ -116,7 +114,7 @@ func (sv *sliceValue) Set(v string) error {
|
|||||||
if sp == "" {
|
if sp == "" {
|
||||||
sp = ":"
|
sp = ":"
|
||||||
}
|
}
|
||||||
return utils.SetValueWithSlice(sv.value, v, sp)
|
return SetValueWithSlice(sv.value, v, sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// errorHandling is a global flag.ErrorHandling
|
// errorHandling is a global flag.ErrorHandling
|
||||||
@ -137,9 +135,9 @@ type Command struct {
|
|||||||
SubCommands map[string]*Command // sub-commands
|
SubCommands map[string]*Command // sub-commands
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a command with given name, the command will use default
|
// NewCLI creates a command with given name, the command will use default
|
||||||
// ErrorHandling: flag.ExitOnError and default usage function: flag.Usage
|
// ErrorHandling: flag.ExitOnError and default usage function: flag.Usage
|
||||||
func New(name string) *Command {
|
func NewCLI(name string) *Command {
|
||||||
cmd := Command{
|
cmd := Command{
|
||||||
Name: name,
|
Name: name,
|
||||||
FlagSet: flag.NewFlagSet(name, errorHandling),
|
FlagSet: flag.NewFlagSet(name, errorHandling),
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package cli
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
@ -27,7 +27,7 @@ import (
|
|||||||
func TestServiceCommand(t *testing.T) {
|
func TestServiceCommand(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
serviceConfig := test.ServiceConfig{}
|
serviceConfig := test.ServiceConfig{}
|
||||||
cmd := New("Service")
|
cmd := NewCLI("Service")
|
||||||
err := cmd.Init(&serviceConfig)
|
err := cmd.Init(&serviceConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Can't init service command. %s", err.Error())
|
t.Errorf("Can't init service command. %s", err.Error())
|
||||||
@ -65,7 +65,7 @@ func TestServiceCommand(t *testing.T) {
|
|||||||
func TestLoginSubCommand(t *testing.T) {
|
func TestLoginSubCommand(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
||||||
cmd := New("Service")
|
cmd := NewCLI("Service")
|
||||||
assert.NoError(cmd.Init(&serviceConfig))
|
assert.NoError(cmd.Init(&serviceConfig))
|
||||||
|
|
||||||
// assert login sub command
|
// assert login sub command
|
||||||
@ -78,7 +78,7 @@ func TestLoginSubCommand(t *testing.T) {
|
|||||||
func TestLoginCommandWithValues(t *testing.T) {
|
func TestLoginCommandWithValues(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
loginConfig := test.LoginConfig{}
|
loginConfig := test.LoginConfig{}
|
||||||
cmd := New("Login")
|
cmd := NewCLI("Login")
|
||||||
assert.NoError(cmd.Init(&loginConfig), "Can't init login command")
|
assert.NoError(cmd.Init(&loginConfig), "Can't init login command")
|
||||||
|
|
||||||
username := "test-user"
|
username := "test-user"
|
||||||
@ -92,7 +92,7 @@ func TestLoginCommandWithValues(t *testing.T) {
|
|||||||
func TestServiceCommandWithValues(t *testing.T) {
|
func TestServiceCommandWithValues(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
||||||
cmd := New("Service")
|
cmd := NewCLI("Service")
|
||||||
assert.NoError(cmd.Init(&serviceConfig))
|
assert.NoError(cmd.Init(&serviceConfig))
|
||||||
|
|
||||||
serviceHost := "service-hostname"
|
serviceHost := "service-hostname"
|
||||||
@ -227,7 +227,7 @@ func TestVariousTypeCommand(t *testing.T) {
|
|||||||
func TestCommandWithSlices(t *testing.T) {
|
func TestCommandWithSlices(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
conf := test.SlicesConfig{}
|
conf := test.SlicesConfig{}
|
||||||
cmd := New("Slice")
|
cmd := NewCLI("Slice")
|
||||||
assert.NoError(cmd.Init(&conf), "Can't init slice command")
|
assert.NoError(cmd.Init(&conf), "Can't init slice command")
|
||||||
|
|
||||||
paths := "/var:/home:/log"
|
paths := "/var:/home:/log"
|
35
config.go
35
config.go
@ -23,9 +23,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"git.mousesoft.ru/ms/config/cli"
|
|
||||||
"git.mousesoft.ru/ms/config/env"
|
|
||||||
"git.mousesoft.ru/ms/config/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,35 +86,35 @@ func parseValue(v reflect.Value) error {
|
|||||||
kind := valueOfField.Kind()
|
kind := valueOfField.Kind()
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
err = utils.SetValueWithBool(valueOfField, defValue)
|
err = SetValueWithBool(valueOfField, defValue)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
valueOfField.SetString(defValue)
|
valueOfField.SetString(defValue)
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
err = utils.SetValueWithIntX(valueOfField, defValue, 8)
|
err = SetValueWithIntX(valueOfField, defValue, 8)
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
err = utils.SetValueWithIntX(valueOfField, defValue, 16)
|
err = SetValueWithIntX(valueOfField, defValue, 16)
|
||||||
case reflect.Int, reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
err = utils.SetValueWithIntX(valueOfField, defValue, 32)
|
err = SetValueWithIntX(valueOfField, defValue, 32)
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
err = utils.SetValueWithIntX(valueOfField, defValue, 64)
|
err = SetValueWithIntX(valueOfField, defValue, 64)
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
err = utils.SetValueWithUintX(valueOfField, defValue, 8)
|
err = SetValueWithUintX(valueOfField, defValue, 8)
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
err = utils.SetValueWithUintX(valueOfField, defValue, 16)
|
err = SetValueWithUintX(valueOfField, defValue, 16)
|
||||||
case reflect.Uint, reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
err = utils.SetValueWithUintX(valueOfField, defValue, 32)
|
err = SetValueWithUintX(valueOfField, defValue, 32)
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
err = utils.SetValueWithUintX(valueOfField, defValue, 64)
|
err = SetValueWithUintX(valueOfField, defValue, 64)
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
err = utils.SetValueWithFloatX(valueOfField, defValue, 32)
|
err = SetValueWithFloatX(valueOfField, defValue, 32)
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
err = utils.SetValueWithFloatX(valueOfField, defValue, 64)
|
err = SetValueWithFloatX(valueOfField, defValue, 64)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
sp, ok := structOfField.Tag.Lookup("separator")
|
sp, ok := structOfField.Tag.Lookup("separator")
|
||||||
if !ok {
|
if !ok {
|
||||||
sp = ":"
|
sp = ":"
|
||||||
}
|
}
|
||||||
err = utils.SetValueWithSlice(valueOfField, defValue, sp)
|
err = SetValueWithSlice(valueOfField, defValue, sp)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type: %s", kind.String())
|
return fmt.Errorf("unsupported type: %s", kind.String())
|
||||||
@ -127,15 +124,9 @@ func parseValue(v reflect.Value) error {
|
|||||||
return err
|
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
|
// ParseCli parses given structure interface and set it with command line input
|
||||||
func ParseCli(i interface{}) error {
|
func ParseCli(i interface{}) error {
|
||||||
cli := cli.New(os.Args[0])
|
cli := NewCLI(os.Args[0])
|
||||||
if err := cli.Init(i); err != nil {
|
if err := cli.Init(i); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -26,21 +26,6 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
LOGIN_USER = "test-login-user"
|
|
||||||
LOGIN_PASSWORD = "test-login-passwd"
|
|
||||||
SERVICE_HOST = "test-service-host"
|
|
||||||
SERVICE_PORT = 8080
|
|
||||||
SERVICE_LOG_PATH = "/var/log/service"
|
|
||||||
SERVICE_LOG_LEVEL = "debug"
|
|
||||||
DB_HOST = "test-db-host"
|
|
||||||
DB_PORT = 9090
|
|
||||||
DB_USER = "test-db-user"
|
|
||||||
DB_PASSWORD = "test-db-password"
|
|
||||||
DB_LOG_PATH = "/var/log/db"
|
|
||||||
DB_LOG_LEVEL = "error"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDefaultValueConfig(t *testing.T) {
|
func TestDefaultValueConfig(t *testing.T) {
|
||||||
conf := test.DefValueConfig{}
|
conf := test.DefValueConfig{}
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
@ -60,29 +45,41 @@ func TestDefaultValueConfig(t *testing.T) {
|
|||||||
func TestEnvConfig(t *testing.T) {
|
func TestEnvConfig(t *testing.T) {
|
||||||
dbLogPrefix := "LOG_"
|
dbLogPrefix := "LOG_"
|
||||||
|
|
||||||
os.Setenv("HOST", DB_HOST)
|
var err error
|
||||||
os.Setenv("PORT", strconv.Itoa(DB_PORT))
|
|
||||||
os.Setenv("USER", DB_USER)
|
|
||||||
os.Setenv("PASSWORD", DB_PASSWORD)
|
|
||||||
os.Setenv(dbLogPrefix+"PATH", DB_LOG_PATH)
|
|
||||||
os.Setenv(dbLogPrefix+"LEVEL", DB_LOG_LEVEL)
|
|
||||||
|
|
||||||
defer os.Unsetenv("HOST")
|
err = os.Setenv("HOST", DB_HOST)
|
||||||
defer os.Unsetenv("PORT")
|
assert.NoError(t, err)
|
||||||
defer os.Unsetenv("USER")
|
|
||||||
defer os.Unsetenv("PASSWORD")
|
err = os.Setenv("PORT", strconv.Itoa(DB_PORT))
|
||||||
defer os.Unsetenv(dbLogPrefix + "PATH")
|
assert.NoError(t, err)
|
||||||
defer os.Unsetenv(dbLogPrefix + "LEVEL")
|
|
||||||
|
err = os.Setenv("USER", DB_USER)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv("PASSWORD", DB_PASSWORD)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbLogPrefix+"PATH", DB_LOG_PATH)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbLogPrefix+"LEVEL", DB_LOG_LEVEL)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv("HOST") }()
|
||||||
|
defer func() { _ = os.Unsetenv("PORT") }()
|
||||||
|
defer func() { _ = os.Unsetenv("USER") }()
|
||||||
|
defer func() { _ = os.Unsetenv("PASSWORD") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbLogPrefix + "PATH") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbLogPrefix + "LEVEL") }()
|
||||||
|
|
||||||
conf := test.DBConfig{}
|
conf := test.DBConfig{}
|
||||||
assert := assert.New(t)
|
assert.NoError(t, ParseEnv(&conf))
|
||||||
assert.NoError(ParseEnv(&conf))
|
assert.Equal(t, DB_HOST, conf.Host)
|
||||||
assert.Equal(DB_HOST, conf.Host)
|
assert.Equal(t, DB_PORT, conf.Port)
|
||||||
assert.Equal(DB_PORT, conf.Port)
|
assert.Equal(t, DB_USER, conf.User)
|
||||||
assert.Equal(DB_USER, conf.User)
|
assert.Equal(t, DB_PASSWORD, conf.Password)
|
||||||
assert.Equal(DB_PASSWORD, conf.Password)
|
assert.Equal(t, DB_LOG_PATH, conf.Log.Path)
|
||||||
assert.Equal(DB_LOG_PATH, conf.Log.Path)
|
assert.Equal(t, DB_LOG_LEVEL, conf.Log.Level)
|
||||||
assert.Equal(DB_LOG_LEVEL, conf.Log.Level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJSONConfigFile(t *testing.T) {
|
func TestJSONConfigFile(t *testing.T) {
|
||||||
|
@ -13,20 +13,18 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package env
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"git.mousesoft.ru/ms/config/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse parses given structure interface, extracts environment definitions
|
// Parse parses given structure interface, extracts environment definitions
|
||||||
// from its tag and sets structure with defined environment variables
|
// from its tag and sets structure with defined environment variables
|
||||||
func Parse(i interface{}) error {
|
func ParseEnv(i interface{}) error {
|
||||||
return ParseWith(i, "")
|
return ParseEnvWith(i, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseWith parses with given structure interface and environment name prefix
|
// ParseWith parses with given structure interface and environment name prefix
|
||||||
@ -43,7 +41,7 @@ func Parse(i interface{}) error {
|
|||||||
//
|
//
|
||||||
// The Server.DB.Host will be mapped to environment variable: DB_HOST which is
|
// 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
|
// concatenated from DB tag in Server struct and Host tag in Database struct
|
||||||
func ParseWith(i interface{}, prefix string) error {
|
func ParseEnvWith(i interface{}, prefix string) error {
|
||||||
ptrRef := reflect.ValueOf(i)
|
ptrRef := reflect.ValueOf(i)
|
||||||
|
|
||||||
if ptrRef.IsNil() || ptrRef.Kind() != reflect.Ptr {
|
if ptrRef.IsNil() || ptrRef.Kind() != reflect.Ptr {
|
||||||
@ -57,11 +55,11 @@ func ParseWith(i interface{}, prefix string) error {
|
|||||||
valueOfStruct.Kind().String())
|
valueOfStruct.Kind().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseValue(valueOfStruct, prefix)
|
return parseValueEnv(valueOfStruct, prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseValue parses a reflect.Value object
|
// parseValue parses a reflect.Value object
|
||||||
func parseValue(v reflect.Value, prefix string) error {
|
func parseValueEnv(v reflect.Value, prefix string) error {
|
||||||
typeOfStruct := v.Type()
|
typeOfStruct := v.Type()
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < v.NumField() && err == nil; i++ {
|
for i := 0; i < v.NumField() && err == nil; i++ {
|
||||||
@ -72,27 +70,27 @@ func parseValue(v reflect.Value, prefix string) error {
|
|||||||
// recursively unmarshal if value is ptr type
|
// recursively unmarshal if value is ptr type
|
||||||
if kindOfField == reflect.Ptr {
|
if kindOfField == reflect.Ptr {
|
||||||
if !valueOfField.IsNil() && valueOfField.CanSet() {
|
if !valueOfField.IsNil() && valueOfField.CanSet() {
|
||||||
err = ParseWith(valueOfField.Interface(),
|
err = ParseEnvWith(valueOfField.Interface(),
|
||||||
prefix+structOfField.Tag.Get("env"))
|
prefix+structOfField.Tag.Get("env"))
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if kindOfField == reflect.Struct {
|
} else if kindOfField == reflect.Struct {
|
||||||
err = parseValue(valueOfField, prefix+structOfField.Tag.Get("env"))
|
err = parseValueEnv(valueOfField, prefix+structOfField.Tag.Get("env"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setFieldValue(valueOfField, structOfField, prefix)
|
err = setFieldValueEnv(valueOfField, structOfField, prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFieldValue sets a reflect.Value with environment value
|
// setFieldValue sets a reflect.Value with environment value
|
||||||
func setFieldValue(v reflect.Value, f reflect.StructField, prefix string) error {
|
func setFieldValueEnv(v reflect.Value, f reflect.StructField, prefix string) error {
|
||||||
envName := f.Tag.Get("env")
|
envName := f.Tag.Get("env")
|
||||||
if envName == "" {
|
if envName == "" {
|
||||||
return nil
|
return nil
|
||||||
@ -111,36 +109,36 @@ func setFieldValue(v reflect.Value, f reflect.StructField, prefix string) error
|
|||||||
kind := v.Kind()
|
kind := v.Kind()
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
err = utils.SetValueWithBool(v, envValue)
|
err = SetValueWithBool(v, envValue)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
v.SetString(envValue)
|
v.SetString(envValue)
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
err = utils.SetValueWithIntX(v, envValue, 8)
|
err = SetValueWithIntX(v, envValue, 8)
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
err = utils.SetValueWithIntX(v, envValue, 16)
|
err = SetValueWithIntX(v, envValue, 16)
|
||||||
case reflect.Int, reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
err = utils.SetValueWithIntX(v, envValue, 32)
|
err = SetValueWithIntX(v, envValue, 32)
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
err = utils.SetValueWithIntX(v, envValue, 64)
|
err = SetValueWithIntX(v, envValue, 64)
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
err = utils.SetValueWithUintX(v, envValue, 8)
|
err = SetValueWithUintX(v, envValue, 8)
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
err = utils.SetValueWithUintX(v, envValue, 16)
|
err = SetValueWithUintX(v, envValue, 16)
|
||||||
case reflect.Uint, reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
err = utils.SetValueWithUintX(v, envValue, 32)
|
err = SetValueWithUintX(v, envValue, 32)
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
err = utils.SetValueWithUintX(v, envValue, 64)
|
err = SetValueWithUintX(v, envValue, 64)
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
err = utils.SetValueWithFloatX(v, envValue, 32)
|
err = SetValueWithFloatX(v, envValue, 32)
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
err = utils.SetValueWithFloatX(v, envValue, 64)
|
err = SetValueWithFloatX(v, envValue, 64)
|
||||||
|
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
sp, ok := f.Tag.Lookup("separator")
|
sp, ok := f.Tag.Lookup("separator")
|
||||||
if !ok {
|
if !ok {
|
||||||
sp = ":"
|
sp = ":"
|
||||||
}
|
}
|
||||||
err = utils.SetValueWithSlice(v, envValue, sp)
|
err = SetValueWithSlice(v, envValue, sp)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type: %s", kind.String())
|
return fmt.Errorf("unsupported type: %s", kind.String())
|
274
env/env_test.go
vendored
274
env/env_test.go
vendored
@ -1,274 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 (
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.mousesoft.ru/ms/config/test"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
LOGIN_USER = "test-login-user"
|
|
||||||
LOGIN_PASSWORD = "test-login-passwd"
|
|
||||||
SERVICE_HOST = "test-service-host"
|
|
||||||
SERVICE_PORT = 8080
|
|
||||||
SERVICE_LOG_PATH = "/var/log/service"
|
|
||||||
SERVICE_LOG_LEVEL = "debug"
|
|
||||||
DB_HOST = "test-db-host"
|
|
||||||
DB_PORT = 9090
|
|
||||||
DB_USER = "test-db-user"
|
|
||||||
DB_PASSWORD = "test-db-password"
|
|
||||||
DB_LOG_PATH = "/var/log/db"
|
|
||||||
DB_LOG_LEVEL = "error"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLoginConfigEnv(t *testing.T) {
|
|
||||||
os.Setenv("USER", LOGIN_USER)
|
|
||||||
os.Setenv("PASSWORD", LOGIN_PASSWORD)
|
|
||||||
defer os.Unsetenv("USER")
|
|
||||||
defer os.Unsetenv("PASSWORD")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
loginConfig := test.LoginConfig{}
|
|
||||||
assert.NoError(Parse(&loginConfig))
|
|
||||||
|
|
||||||
assert.Equal(LOGIN_USER, loginConfig.User)
|
|
||||||
assert.Equal(LOGIN_PASSWORD, loginConfig.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoginConfigEnvWithPrefix(t *testing.T) {
|
|
||||||
os.Setenv("DB_USER", LOGIN_USER)
|
|
||||||
os.Setenv("DB_PASSWORD", LOGIN_PASSWORD)
|
|
||||||
defer os.Unsetenv("DB_USER")
|
|
||||||
defer os.Unsetenv("DB_PASSWORD")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
loginConfig := test.LoginConfig{}
|
|
||||||
assert.NoError(ParseWith(&loginConfig, "DB_"))
|
|
||||||
assert.Equal(LOGIN_USER, loginConfig.User)
|
|
||||||
assert.Equal(LOGIN_PASSWORD, loginConfig.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServiceConfigEnv(t *testing.T) {
|
|
||||||
servicePrefix := "CONFIG_TEST_SERVICE_"
|
|
||||||
serviceLogPrefix := servicePrefix + "LOG_"
|
|
||||||
dbPrefix := servicePrefix + "DB_"
|
|
||||||
dbLogPrefix := dbPrefix + "LOG_"
|
|
||||||
|
|
||||||
os.Setenv(servicePrefix+"HOST", SERVICE_HOST)
|
|
||||||
os.Setenv(servicePrefix+"PORT", strconv.Itoa(SERVICE_PORT))
|
|
||||||
os.Setenv(serviceLogPrefix+"PATH", SERVICE_LOG_PATH)
|
|
||||||
os.Setenv(serviceLogPrefix+"LEVEL", SERVICE_LOG_LEVEL)
|
|
||||||
os.Setenv(dbPrefix+"HOST", DB_HOST)
|
|
||||||
os.Setenv(dbPrefix+"PORT", strconv.Itoa(DB_PORT))
|
|
||||||
os.Setenv(dbPrefix+"USER", DB_USER)
|
|
||||||
os.Setenv(dbPrefix+"PASSWORD", DB_PASSWORD)
|
|
||||||
os.Setenv(dbLogPrefix+"PATH", DB_LOG_PATH)
|
|
||||||
os.Setenv(dbLogPrefix+"LEVEL", DB_LOG_LEVEL)
|
|
||||||
|
|
||||||
defer os.Unsetenv(servicePrefix + "HOST")
|
|
||||||
defer os.Unsetenv(servicePrefix + "PORT")
|
|
||||||
defer os.Unsetenv(serviceLogPrefix + "PATH")
|
|
||||||
defer os.Unsetenv(serviceLogPrefix + "LEVEL")
|
|
||||||
defer os.Unsetenv(dbPrefix + "HOST")
|
|
||||||
defer os.Unsetenv(dbPrefix + "PORT")
|
|
||||||
defer os.Unsetenv(dbPrefix + "USER")
|
|
||||||
defer os.Unsetenv(dbPrefix + "PASSWORD")
|
|
||||||
defer os.Unsetenv(dbLogPrefix + "PATH")
|
|
||||||
defer os.Unsetenv(dbLogPrefix + "LEVEL")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
serviceConfig := test.ServiceConfig{}
|
|
||||||
assert.NoError(Parse(&serviceConfig))
|
|
||||||
assert.Equal(SERVICE_HOST, serviceConfig.Host)
|
|
||||||
assert.Equal(SERVICE_PORT, serviceConfig.Port)
|
|
||||||
assert.Equal(SERVICE_LOG_PATH, serviceConfig.Log.Path)
|
|
||||||
assert.Equal(SERVICE_LOG_LEVEL, serviceConfig.Log.Level)
|
|
||||||
assert.Equal(DB_HOST, serviceConfig.DBConfig.Host)
|
|
||||||
assert.Equal(DB_PORT, serviceConfig.DBConfig.Port)
|
|
||||||
assert.Equal(DB_USER, serviceConfig.DBConfig.User)
|
|
||||||
assert.Equal(DB_PASSWORD, serviceConfig.DBConfig.Password)
|
|
||||||
assert.Equal(DB_LOG_PATH, serviceConfig.DBConfig.Log.Path)
|
|
||||||
assert.Equal(DB_LOG_LEVEL, serviceConfig.DBConfig.Log.Level)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServiceLoginConfigEnv(t *testing.T) {
|
|
||||||
serviceLoginPrefix := "CONFIG_TEST_SERVICE_LOGIN_"
|
|
||||||
os.Setenv(serviceLoginPrefix+"USER", LOGIN_USER)
|
|
||||||
os.Setenv(serviceLoginPrefix+"PASSWORD", LOGIN_PASSWORD)
|
|
||||||
defer os.Unsetenv(serviceLoginPrefix + "USER")
|
|
||||||
defer os.Unsetenv(serviceLoginPrefix + "PASSWORD")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
|
||||||
assert.NoError(Parse(&serviceConfig))
|
|
||||||
assert.Equal(LOGIN_USER, serviceConfig.Login.User)
|
|
||||||
assert.Equal(LOGIN_PASSWORD, serviceConfig.Login.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTypesConfigEnv(t *testing.T) {
|
|
||||||
typesPrefix := "CONFIG_TEST_"
|
|
||||||
os.Setenv(typesPrefix+"BOOL", "true")
|
|
||||||
os.Setenv(typesPrefix+"STR", "test-string")
|
|
||||||
os.Setenv(typesPrefix+"INT8", "100")
|
|
||||||
os.Setenv(typesPrefix+"INT16", "1000")
|
|
||||||
os.Setenv(typesPrefix+"INT", "10000")
|
|
||||||
os.Setenv(typesPrefix+"INT32", "100000")
|
|
||||||
os.Setenv(typesPrefix+"INT64", "1000000")
|
|
||||||
os.Setenv(typesPrefix+"UINT8", "200")
|
|
||||||
os.Setenv(typesPrefix+"UINT16", "2000")
|
|
||||||
os.Setenv(typesPrefix+"UINT", "20000")
|
|
||||||
os.Setenv(typesPrefix+"UINT32", "200000")
|
|
||||||
os.Setenv(typesPrefix+"UINT64", "2000000")
|
|
||||||
os.Setenv(typesPrefix+"FLOAT32", "1.234")
|
|
||||||
os.Setenv(typesPrefix+"FLOAT64", "2222.33333")
|
|
||||||
|
|
||||||
defer os.Unsetenv(typesPrefix + "BOOL")
|
|
||||||
defer os.Unsetenv(typesPrefix + "STR")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT8")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT16")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT64")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT8")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT16")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT64")
|
|
||||||
defer os.Unsetenv(typesPrefix + "FLOAT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "FLOAT64")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
typesConfig := test.TypesConfig{}
|
|
||||||
assert.NoError(Parse(&typesConfig))
|
|
||||||
assert.Equal(true, typesConfig.BoolValue)
|
|
||||||
assert.Equal("test-string", typesConfig.StrValue)
|
|
||||||
assert.Equal(int8(100), typesConfig.Int8Value)
|
|
||||||
assert.Equal(int16(1000), typesConfig.Int16Value)
|
|
||||||
assert.Equal(10000, typesConfig.IntValue)
|
|
||||||
assert.Equal(int32(100000), typesConfig.Int32Value)
|
|
||||||
assert.Equal(int64(1000000), typesConfig.Int64Value)
|
|
||||||
assert.Equal(uint8(200), typesConfig.Uint8Value)
|
|
||||||
assert.Equal(uint16(2000), typesConfig.Uint16Value)
|
|
||||||
assert.Equal(uint(20000), typesConfig.UintValue)
|
|
||||||
assert.Equal(uint32(200000), typesConfig.Uint32Value)
|
|
||||||
assert.Equal(uint64(2000000), typesConfig.Uint64Value)
|
|
||||||
assert.Equal(float32(1.234), typesConfig.Float32Value)
|
|
||||||
assert.Equal(float64(2222.33333), typesConfig.Float64Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTypesConfigWithErrorEnv(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
typesConfig := test.TypesConfig{}
|
|
||||||
typesPrefix := "CONFIG_TEST_"
|
|
||||||
os.Setenv(typesPrefix+"BOOL", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "BOOL")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"INT8", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "INT8")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"INT16", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "INT16")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"INT", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "INT")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"INT32", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "INT32")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"INT64", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "INT64")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"UINT8", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "UINT8")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"UINT16", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "UINT16")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"UINT", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "UINT")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"UINT32", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "UINT32")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"UINT64", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "UINT64")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"FLOAT32", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "FLOAT32")
|
|
||||||
|
|
||||||
os.Setenv(typesPrefix+"FLOAT64", "xxx")
|
|
||||||
assert.Error(Parse(&typesConfig))
|
|
||||||
os.Unsetenv(typesPrefix + "FLOAT64")
|
|
||||||
|
|
||||||
defer os.Unsetenv(typesPrefix + "BOOL")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT8")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT16")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "INT64")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT8")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT16")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "UINT64")
|
|
||||||
defer os.Unsetenv(typesPrefix + "FLOAT32")
|
|
||||||
defer os.Unsetenv(typesPrefix + "FLOAT64")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSlicesConfigEnv(t *testing.T) {
|
|
||||||
prefix := "CONFIG_TEST_SLICES_"
|
|
||||||
os.Setenv(prefix+"PATHS", "/var:/usr:/home")
|
|
||||||
os.Setenv(prefix+"DEBUG", "/root;/log;/opt")
|
|
||||||
os.Setenv(prefix+"VALUES", "1,2,4,5")
|
|
||||||
|
|
||||||
defer os.Unsetenv(prefix + "PATHS")
|
|
||||||
defer os.Unsetenv(prefix + "DEBUG")
|
|
||||||
defer os.Unsetenv(prefix + "VALUES")
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
conf := test.SlicesConfig{}
|
|
||||||
assert.NoError(Parse(&conf))
|
|
||||||
assert.Equal(3, len(conf.Paths))
|
|
||||||
assert.Equal("/var", conf.Paths[0])
|
|
||||||
assert.Equal("/usr", conf.Paths[1])
|
|
||||||
assert.Equal("/home", conf.Paths[2])
|
|
||||||
assert.Equal(3, len(conf.Debugs))
|
|
||||||
assert.Equal("/root", conf.Debugs[0])
|
|
||||||
assert.Equal("/log", conf.Debugs[1])
|
|
||||||
assert.Equal("/opt", conf.Debugs[2])
|
|
||||||
assert.Equal(4, len(conf.Values))
|
|
||||||
assert.Equal(1, conf.Values[0])
|
|
||||||
assert.Equal(2, conf.Values[1])
|
|
||||||
assert.Equal(4, conf.Values[2])
|
|
||||||
assert.Equal(5, conf.Values[3])
|
|
||||||
}
|
|
401
env_test.go
Normal file
401
env_test.go
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.mousesoft.ru/ms/config/test"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LOGIN_USER = "test-login-user"
|
||||||
|
LOGIN_PASSWORD = "test-login-passwd"
|
||||||
|
SERVICE_HOST = "test-service-host"
|
||||||
|
SERVICE_PORT = 8080
|
||||||
|
SERVICE_LOG_PATH = "/var/log/service"
|
||||||
|
SERVICE_LOG_LEVEL = "debug"
|
||||||
|
DB_HOST = "test-db-host"
|
||||||
|
DB_PORT = 9090
|
||||||
|
DB_USER = "test-db-user"
|
||||||
|
DB_PASSWORD = "test-db-password"
|
||||||
|
DB_LOG_PATH = "/var/log/db"
|
||||||
|
DB_LOG_LEVEL = "error"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoginConfigEnv(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = os.Setenv("USER", LOGIN_USER)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv("PASSWORD", LOGIN_PASSWORD)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv("USER") }()
|
||||||
|
defer func() { _ = os.Unsetenv("PASSWORD") }()
|
||||||
|
|
||||||
|
loginConfig := test.LoginConfig{}
|
||||||
|
assert.NoError(t, ParseEnv(&loginConfig))
|
||||||
|
|
||||||
|
assert.Equal(t, LOGIN_USER, loginConfig.User)
|
||||||
|
assert.Equal(t, LOGIN_PASSWORD, loginConfig.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginConfigEnvWithPrefix(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = os.Setenv("DB_USER", LOGIN_USER)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv("DB_PASSWORD", LOGIN_PASSWORD)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv("DB_USER") }()
|
||||||
|
defer func() { _ = os.Unsetenv("DB_PASSWORD") }()
|
||||||
|
|
||||||
|
loginConfig := test.LoginConfig{}
|
||||||
|
assert.NoError(t, ParseEnvWith(&loginConfig, "DB_"))
|
||||||
|
assert.Equal(t, LOGIN_USER, loginConfig.User)
|
||||||
|
assert.Equal(t, LOGIN_PASSWORD, loginConfig.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceConfigEnv(t *testing.T) {
|
||||||
|
servicePrefix := "CONFIG_TEST_SERVICE_"
|
||||||
|
serviceLogPrefix := servicePrefix + "LOG_"
|
||||||
|
dbPrefix := servicePrefix + "DB_"
|
||||||
|
dbLogPrefix := dbPrefix + "LOG_"
|
||||||
|
|
||||||
|
err := os.Setenv(servicePrefix+"HOST", SERVICE_HOST)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(servicePrefix+"PORT", strconv.Itoa(SERVICE_PORT))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(serviceLogPrefix+"PATH", SERVICE_LOG_PATH)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(serviceLogPrefix+"LEVEL", SERVICE_LOG_LEVEL)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbPrefix+"HOST", DB_HOST)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbPrefix+"PORT", strconv.Itoa(DB_PORT))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbPrefix+"USER", DB_USER)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbPrefix+"PASSWORD", DB_PASSWORD)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbLogPrefix+"PATH", DB_LOG_PATH)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(dbLogPrefix+"LEVEL", DB_LOG_LEVEL)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv(servicePrefix + "HOST") }()
|
||||||
|
defer func() { _ = os.Unsetenv(servicePrefix + "PORT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(serviceLogPrefix + "PATH") }()
|
||||||
|
defer func() { _ = os.Unsetenv(serviceLogPrefix + "LEVEL") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbPrefix + "HOST") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbPrefix + "PORT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbPrefix + "USER") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbPrefix + "PASSWORD") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbLogPrefix + "PATH") }()
|
||||||
|
defer func() { _ = os.Unsetenv(dbLogPrefix + "LEVEL") }()
|
||||||
|
|
||||||
|
serviceConfig := test.ServiceConfig{}
|
||||||
|
assert.NoError(t, ParseEnv(&serviceConfig))
|
||||||
|
assert.Equal(t, SERVICE_HOST, serviceConfig.Host)
|
||||||
|
assert.Equal(t, SERVICE_PORT, serviceConfig.Port)
|
||||||
|
assert.Equal(t, SERVICE_LOG_PATH, serviceConfig.Log.Path)
|
||||||
|
assert.Equal(t, SERVICE_LOG_LEVEL, serviceConfig.Log.Level)
|
||||||
|
assert.Equal(t, DB_HOST, serviceConfig.DBConfig.Host)
|
||||||
|
assert.Equal(t, DB_PORT, serviceConfig.DBConfig.Port)
|
||||||
|
assert.Equal(t, DB_USER, serviceConfig.DBConfig.User)
|
||||||
|
assert.Equal(t, DB_PASSWORD, serviceConfig.DBConfig.Password)
|
||||||
|
assert.Equal(t, DB_LOG_PATH, serviceConfig.DBConfig.Log.Path)
|
||||||
|
assert.Equal(t, DB_LOG_LEVEL, serviceConfig.DBConfig.Log.Level)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceLoginConfigEnv(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
serviceLoginPrefix := "CONFIG_TEST_SERVICE_LOGIN_"
|
||||||
|
|
||||||
|
err = os.Setenv(serviceLoginPrefix+"USER", LOGIN_USER)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(serviceLoginPrefix+"PASSWORD", LOGIN_PASSWORD)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv(serviceLoginPrefix + "USER") }()
|
||||||
|
defer func() { _ = os.Unsetenv(serviceLoginPrefix + "PASSWORD") }()
|
||||||
|
|
||||||
|
serviceConfig := test.ServiceConfig{Login: &test.LoginConfig{}}
|
||||||
|
assert.NoError(t, ParseEnv(&serviceConfig))
|
||||||
|
assert.Equal(t, LOGIN_USER, serviceConfig.Login.User)
|
||||||
|
assert.Equal(t, LOGIN_PASSWORD, serviceConfig.Login.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTypesConfigEnv(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
typesPrefix := "CONFIG_TEST_"
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"BOOL", "true")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"STR", "test-string")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT8", "100")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT16", "1000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT", "10000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT32", "100000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT64", "1000000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT8", "200")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT16", "2000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT", "20000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT32", "200000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT64", "2000000")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"FLOAT32", "1.234")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"FLOAT64", "2222.33333")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "BOOL") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "STR") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT8") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT16") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT64") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT8") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT16") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT64") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "FLOAT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "FLOAT64") }()
|
||||||
|
|
||||||
|
typesConfig := test.TypesConfig{}
|
||||||
|
|
||||||
|
err = ParseEnv(&typesConfig)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.True(t, typesConfig.BoolValue)
|
||||||
|
assert.Equal(t, "test-string", typesConfig.StrValue)
|
||||||
|
assert.Equal(t, int8(100), typesConfig.Int8Value)
|
||||||
|
assert.Equal(t, int16(1000), typesConfig.Int16Value)
|
||||||
|
assert.Equal(t, 10000, typesConfig.IntValue)
|
||||||
|
assert.Equal(t, int32(100000), typesConfig.Int32Value)
|
||||||
|
assert.Equal(t, int64(1000000), typesConfig.Int64Value)
|
||||||
|
assert.Equal(t, uint8(200), typesConfig.Uint8Value)
|
||||||
|
assert.Equal(t, uint16(2000), typesConfig.Uint16Value)
|
||||||
|
assert.Equal(t, uint(20000), typesConfig.UintValue)
|
||||||
|
assert.Equal(t, uint32(200000), typesConfig.Uint32Value)
|
||||||
|
assert.Equal(t, uint64(2000000), typesConfig.Uint64Value)
|
||||||
|
assert.Equal(t, float32(1.234), typesConfig.Float32Value)
|
||||||
|
assert.Equal(t, float64(2222.33333), typesConfig.Float64Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTypesConfigWithErrorEnv(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
typesConfig := test.TypesConfig{}
|
||||||
|
typesPrefix := "CONFIG_TEST_"
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"BOOL", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "BOOL")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT8", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "INT8")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT16", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "INT16")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "INT")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT32", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "INT32")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"INT64", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "INT64")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT8", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "UINT8")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT16", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "UINT16")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "UINT")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT32", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "UINT32")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"UINT64", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "UINT64")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"FLOAT32", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "FLOAT32")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(typesPrefix+"FLOAT64", "xxx")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Error(t, ParseEnv(&typesConfig))
|
||||||
|
|
||||||
|
err = os.Unsetenv(typesPrefix + "FLOAT64")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "BOOL") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT8") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT16") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "INT64") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT8") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT16") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "UINT64") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "FLOAT32") }()
|
||||||
|
defer func() { _ = os.Unsetenv(typesPrefix + "FLOAT64") }()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlicesConfigEnv(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
prefix := "CONFIG_TEST_SLICES_"
|
||||||
|
|
||||||
|
err = os.Setenv(prefix+"PATHS", "/var:/usr:/home")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(prefix+"DEBUG", "/root;/log;/opt")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = os.Setenv(prefix+"VALUES", "1,2,4,5")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() { _ = os.Unsetenv(prefix + "PATHS") }()
|
||||||
|
defer func() { _ = os.Unsetenv(prefix + "DEBUG") }()
|
||||||
|
defer func() { _ = os.Unsetenv(prefix + "VALUES") }()
|
||||||
|
|
||||||
|
conf := test.SlicesConfig{}
|
||||||
|
assert.NoError(t, ParseEnv(&conf))
|
||||||
|
assert.Equal(t, 3, len(conf.Paths))
|
||||||
|
assert.Equal(t, "/var", conf.Paths[0])
|
||||||
|
assert.Equal(t, "/usr", conf.Paths[1])
|
||||||
|
assert.Equal(t, "/home", conf.Paths[2])
|
||||||
|
assert.Equal(t, 3, len(conf.Debugs))
|
||||||
|
assert.Equal(t, "/root", conf.Debugs[0])
|
||||||
|
assert.Equal(t, "/log", conf.Debugs[1])
|
||||||
|
assert.Equal(t, "/opt", conf.Debugs[2])
|
||||||
|
assert.Equal(t, 4, len(conf.Values))
|
||||||
|
assert.Equal(t, 1, conf.Values[0])
|
||||||
|
assert.Equal(t, 2, conf.Values[1])
|
||||||
|
assert.Equal(t, 4, conf.Values[2])
|
||||||
|
assert.Equal(t, 5, conf.Values[3])
|
||||||
|
}
|
110
makefile
Normal file
110
makefile
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# chess-record makefile
|
||||||
|
# =====================
|
||||||
|
|
||||||
|
SHELL := /usr/bin/env bash
|
||||||
|
|
||||||
|
PROJECT_ID := config
|
||||||
|
PROJECT_NAME ?= MouseSoft Config
|
||||||
|
BIN_SUFFIX :=
|
||||||
|
|
||||||
|
TMPDIR ?= $(CURDIR)/tmp
|
||||||
|
OUTDIR ?= $(CURDIR)/out
|
||||||
|
BINDIR ?= $(OUTDIR)/bin
|
||||||
|
|
||||||
|
VERSION ?= $(strip $(shell ./scripts/version.sh))
|
||||||
|
VERSION_NUMBER := $(strip $(shell ./scripts/version.sh number))
|
||||||
|
|
||||||
|
BUILD_ARCH ?= $(shell go env GOARCH)
|
||||||
|
BUILD_OS ?= $(shell go env GOOS)
|
||||||
|
|
||||||
|
GOCMD := go
|
||||||
|
GOTEST := $(GOCMD) test
|
||||||
|
GOVET := $(GOCMD) vet
|
||||||
|
ECHO_CMD := echo -e
|
||||||
|
|
||||||
|
GREEN := $(shell tput -Txterm setaf 2)
|
||||||
|
YELLOW := $(shell tput -Txterm setaf 3)
|
||||||
|
WHITE := $(shell tput -Txterm setaf 7)
|
||||||
|
CYAN := $(shell tput -Txterm setaf 6)
|
||||||
|
RESET := $(shell tput -Txterm sgr0)
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
|
version: ## Version of the project to be built
|
||||||
|
@echo $(VERSION)
|
||||||
|
.PHONY:version
|
||||||
|
|
||||||
|
version-number: ## Version number of the project to be built
|
||||||
|
@echo $(VERSION_NUMBER)
|
||||||
|
.PHONY:version-number
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
all: clean vendor test ## Build binary
|
||||||
|
.PHONY:all
|
||||||
|
|
||||||
|
vendor: ## Copy of all packages needed to support builds and tests in the vendor directory
|
||||||
|
$(GOCMD) mod vendor
|
||||||
|
@$(ECHO_CMD) "Vendor\t\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:vendor
|
||||||
|
|
||||||
|
clean: ## Remove build related files
|
||||||
|
@rm -fr $(TMPDIR)
|
||||||
|
@rm -fr $(OUTDIR)
|
||||||
|
@$(ECHO_CMD) "Clean\t\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:clean
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
test: ## Run the tests of the project
|
||||||
|
ifeq ($(EXPORT_RESULT), true)
|
||||||
|
@mkdir -p $(OUTDIR)
|
||||||
|
$(eval OUTPUT_OPTIONS = | go-junit-report -set-exit-code > $(OUTDIR)/junit-report.xml)
|
||||||
|
endif
|
||||||
|
$(GOTEST) -v $(GO_OPT) ./... $(OUTPUT_OPTIONS)
|
||||||
|
@$(ECHO_CMD) "Test\t\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:test
|
||||||
|
|
||||||
|
coverage: ## Run the tests of the project and export the coverage report.
|
||||||
|
@mkdir -p out
|
||||||
|
$(GOTEST) -cover -covermode=count -coverprofile=$(OUTDIR)/profile.cov ./...
|
||||||
|
$(GOCMD) tool cover -func $(OUTDIR)/profile.cov
|
||||||
|
ifeq ($(EXPORT_RESULT), true)
|
||||||
|
ifeq ($(COVERAGE_FORMAT), html)
|
||||||
|
gocov convert $(OUTDIR)/profile.cov | gocov-html > $(OUTDIR)/coverage.html
|
||||||
|
else
|
||||||
|
gocov convert $(OUTDIR)/profile.cov | gocov-xml > $(OUTDIR)/coverage.xml
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
@$(ECHO_CMD) "Coverage\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:coverage
|
||||||
|
|
||||||
|
## Lint
|
||||||
|
|
||||||
|
lint: ## Run all available linters.
|
||||||
|
go vet ./...
|
||||||
|
errcheck ./...
|
||||||
|
staticcheck ./...
|
||||||
|
usestdlibvars ./...
|
||||||
|
shadow ./...
|
||||||
|
@$(ECHO_CMD) "Lint\t\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:lint
|
||||||
|
|
||||||
|
golangci-lint: ## Run golangci-lint linter
|
||||||
|
@golangci-lint run
|
||||||
|
@$(ECHO_CMD) "GolangCI Lint\t${GREEN}[OK]${RESET}"
|
||||||
|
.PHONY:golangci-lint
|
||||||
|
|
||||||
|
## Help
|
||||||
|
|
||||||
|
help: ## Show this help.
|
||||||
|
@$(ECHO_CMD) ''
|
||||||
|
@$(ECHO_CMD) 'Usage:'
|
||||||
|
@$(ECHO_CMD) ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
|
||||||
|
@$(ECHO_CMD) ''
|
||||||
|
@$(ECHO_CMD) 'Targets:'
|
||||||
|
@awk 'BEGIN {FS = ":.*?## "} { \
|
||||||
|
if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${YELLOW}%-20s${GREEN}%s${RESET}\n", $$1, $$2} \
|
||||||
|
else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \
|
||||||
|
}' $(MAKEFILE_LIST)
|
||||||
|
.PHONY:help
|
20
scripts/changes.awk
Normal file
20
scripts/changes.awk
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Get changes of given version number.
|
||||||
|
{
|
||||||
|
while (index($0, "## [" version "]") <= 0) {
|
||||||
|
if (getline <= 0) {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getline <= 0 ) {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if (getline <= 0 ) {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
while (index($0, "## [") <= 0) {
|
||||||
|
print $0
|
||||||
|
if (getline <= 0) {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
scripts/version.sh
Executable file
22
scripts/version.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ -z ${TAG_NAME+x} ]; then
|
||||||
|
if [ -z ${BRANCH_NAME+x} ]; then
|
||||||
|
BRANCH_NAME=$(echo $(git branch --show-current) || \
|
||||||
|
echo $(git name-rev --name-only HEAD))
|
||||||
|
fi
|
||||||
|
GIT_VERSION=$(echo ${BRANCH_NAME} | grep -q 'release/' \
|
||||||
|
&& echo ${BRANCH_NAME} | sed -e 's|release/|v|' -e 's/$/-RC/' || \
|
||||||
|
echo $(git describe --always --tags --dirty 2>/dev/null) || echo v0)
|
||||||
|
else
|
||||||
|
GIT_VERSION=${TAG_NAME}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z ${VERSION+x} ]; then
|
||||||
|
VERSION=$(echo ${GIT_VERSION} | sed -e 's|^origin/||')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z $1 ]; then
|
||||||
|
echo "${VERSION}"
|
||||||
|
else
|
||||||
|
echo ${VERSION} | sed -e 's/^v//'
|
||||||
|
fi
|
@ -5,4 +5,3 @@ dbPassword: test-db-password
|
|||||||
log:
|
log:
|
||||||
path: /var/log/db
|
path: /var/log/db
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package utils
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -97,7 +97,7 @@ func SetValueWithSlice(v reflect.Value, slice string, separator string) error {
|
|||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
err = SetValueWithFloatX(ele, data[i], 64)
|
err = SetValueWithFloatX(ele, data[i], 64)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Can't support type: %s", kind.String())
|
return fmt.Errorf("unsupported type: %s", kind.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package utils
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
Loading…
Reference in New Issue
Block a user