mirror of
https://github.com/zrepl/zrepl.git
synced 2025-06-25 04:01:49 +02:00
envconst: queryable report of resolved variables + integration inot zrepl status --raw
fixes #299 refs #186
This commit is contained in:
parent
b330ccca5d
commit
4b1b7a8561
@ -120,7 +120,13 @@ func (j *controlJob) Run(ctx context.Context) {
|
|||||||
jsonResponder{log, func() (interface{}, error) {
|
jsonResponder{log, func() (interface{}, error) {
|
||||||
jobs := j.jobs.status()
|
jobs := j.jobs.status()
|
||||||
globalZFS := zfscmd.GetReport()
|
globalZFS := zfscmd.GetReport()
|
||||||
s := Status{Jobs: jobs, Global: GlobalStatus{ZFSCmds: globalZFS}}
|
envconstReport := envconst.GetReport()
|
||||||
|
s := Status{
|
||||||
|
Jobs: jobs,
|
||||||
|
Global: GlobalStatus{
|
||||||
|
ZFSCmds: globalZFS,
|
||||||
|
Envconst: envconstReport,
|
||||||
|
}}
|
||||||
return s, nil
|
return s, nil
|
||||||
}})
|
}})
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/zrepl/zrepl/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
"github.com/zrepl/zrepl/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
@ -151,6 +152,7 @@ type Status struct {
|
|||||||
|
|
||||||
type GlobalStatus struct {
|
type GlobalStatus struct {
|
||||||
ZFSCmds *zfscmd.Report
|
ZFSCmds *zfscmd.Report
|
||||||
|
Envconst *envconst.Report
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *jobs) status() map[string]*job.Status {
|
func (s *jobs) status() map[string]*job.Status {
|
||||||
|
@ -12,84 +12,100 @@ import (
|
|||||||
|
|
||||||
var cache sync.Map
|
var cache sync.Map
|
||||||
|
|
||||||
func Duration(varname string, def time.Duration) time.Duration {
|
func Reset() {
|
||||||
|
cache.Range(func(key, _ interface{}) bool {
|
||||||
|
cache.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Duration(varname string, def time.Duration) (d time.Duration) {
|
||||||
|
var err error
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(time.Duration)
|
return v.(time.Duration)
|
||||||
}
|
}
|
||||||
e := os.Getenv(varname)
|
e := os.Getenv(varname)
|
||||||
if e == "" {
|
if e == "" {
|
||||||
return def
|
d = def
|
||||||
}
|
} else {
|
||||||
d, err := time.ParseDuration(e)
|
d, err = time.ParseDuration(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cache.Store(varname, d)
|
cache.Store(varname, d)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int(varname string, def int) int {
|
func Int(varname string, def int) (d int) {
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(int)
|
return v.(int)
|
||||||
}
|
}
|
||||||
e := os.Getenv(varname)
|
e := os.Getenv(varname)
|
||||||
if e == "" {
|
if e == "" {
|
||||||
return def
|
d = def
|
||||||
}
|
} else {
|
||||||
d64, err := strconv.ParseInt(e, 10, strconv.IntSize)
|
d64, err := strconv.ParseInt(e, 10, strconv.IntSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
d := int(d64)
|
d = int(d64)
|
||||||
|
}
|
||||||
cache.Store(varname, d)
|
cache.Store(varname, d)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int64(varname string, def int64) int64 {
|
func Int64(varname string, def int64) (d int64) {
|
||||||
|
var err error
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(int64)
|
return v.(int64)
|
||||||
}
|
}
|
||||||
e := os.Getenv(varname)
|
e := os.Getenv(varname)
|
||||||
if e == "" {
|
if e == "" {
|
||||||
return def
|
d = def
|
||||||
}
|
} else {
|
||||||
d, err := strconv.ParseInt(e, 10, 64)
|
d, err = strconv.ParseInt(e, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cache.Store(varname, d)
|
cache.Store(varname, d)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bool(varname string, def bool) bool {
|
func Bool(varname string, def bool) (d bool) {
|
||||||
|
var err error
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(bool)
|
return v.(bool)
|
||||||
}
|
}
|
||||||
e := os.Getenv(varname)
|
e := os.Getenv(varname)
|
||||||
if e == "" {
|
if e == "" {
|
||||||
return def
|
d = def
|
||||||
}
|
} else {
|
||||||
d, err := strconv.ParseBool(e)
|
d, err = strconv.ParseBool(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cache.Store(varname, d)
|
cache.Store(varname, d)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func String(varname string, def string) string {
|
func String(varname string, def string) (d string) {
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(string)
|
return v.(string)
|
||||||
}
|
}
|
||||||
e := os.Getenv(varname)
|
e := os.Getenv(varname)
|
||||||
if e == "" {
|
if e == "" {
|
||||||
return def
|
d = def
|
||||||
|
} else {
|
||||||
|
d = e
|
||||||
}
|
}
|
||||||
cache.Store(varname, e)
|
cache.Store(varname, d)
|
||||||
return e
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func Var(varname string, def flag.Value) interface{} {
|
func Var(varname string, def flag.Value) (d interface{}) {
|
||||||
|
|
||||||
// use def's type to instantiate a new object of that same type
|
// use def's type to instantiate a new object of that same type
|
||||||
// and call flag.Value.Set() on it
|
// and call flag.Value.Set() on it
|
||||||
@ -100,19 +116,43 @@ func Var(varname string, def flag.Value) interface{} {
|
|||||||
defElemType := defType.Elem()
|
defElemType := defType.Elem()
|
||||||
|
|
||||||
if v, ok := cache.Load(varname); ok {
|
if v, ok := cache.Load(varname); ok {
|
||||||
return v.(string)
|
return v
|
||||||
}
|
|
||||||
e := os.Getenv(varname)
|
|
||||||
if e == "" {
|
|
||||||
return def
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e := os.Getenv(varname)
|
||||||
|
if e == "" {
|
||||||
|
d = def
|
||||||
|
} else {
|
||||||
newInstance := reflect.New(defElemType)
|
newInstance := reflect.New(defElemType)
|
||||||
if err := newInstance.Interface().(flag.Value).Set(e); err != nil {
|
if err := newInstance.Interface().(flag.Value).Set(e); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
d = newInstance.Interface()
|
||||||
res := newInstance.Interface()
|
}
|
||||||
cache.Store(varname, res)
|
|
||||||
return res
|
cache.Store(varname, d)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
type Report struct {
|
||||||
|
Entries []EntryReport
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntryReport struct {
|
||||||
|
Var string
|
||||||
|
Value string
|
||||||
|
ValueGoType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetReport() *Report {
|
||||||
|
var r Report
|
||||||
|
cache.Range(func(key, value interface{}) bool {
|
||||||
|
r.Entries = append(r.Entries, EntryReport{
|
||||||
|
Var: key.(string),
|
||||||
|
Value: fmt.Sprintf("%v", value),
|
||||||
|
ValueGoType: fmt.Sprintf("%T", value),
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &r
|
||||||
}
|
}
|
||||||
|
@ -32,19 +32,27 @@ func (m *ExampleVarType) Set(s string) error {
|
|||||||
|
|
||||||
const EnvVarName = "ZREPL_ENVCONST_UNIT_TEST_VAR"
|
const EnvVarName = "ZREPL_ENVCONST_UNIT_TEST_VAR"
|
||||||
|
|
||||||
func TestVar(t *testing.T) {
|
func TestVarDefaultValue(t *testing.T) {
|
||||||
|
envconst.Reset()
|
||||||
_, set := os.LookupEnv(EnvVarName)
|
_, set := os.LookupEnv(EnvVarName)
|
||||||
require.False(t, set)
|
require.False(t, set)
|
||||||
defer os.Unsetenv(EnvVarName)
|
defer os.Unsetenv(EnvVarName)
|
||||||
|
|
||||||
val := envconst.Var(EnvVarName, &Var1)
|
val := envconst.Var(EnvVarName, &Var1)
|
||||||
if &Var1 != val {
|
if &Var1 != val {
|
||||||
t.Errorf("default value shut be same address")
|
t.Errorf("default value should be same address")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVarOverriddenValue(t *testing.T) {
|
||||||
|
envconst.Reset()
|
||||||
|
_, set := os.LookupEnv(EnvVarName)
|
||||||
|
require.False(t, set)
|
||||||
|
defer os.Unsetenv(EnvVarName)
|
||||||
|
|
||||||
err := os.Setenv(EnvVarName, "var2")
|
err := os.Setenv(EnvVarName, "var2")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
val = envconst.Var(EnvVarName, &Var1)
|
val := envconst.Var(EnvVarName, &Var1)
|
||||||
require.Equal(t, &Var2, val, "only structural identity is required for non-default vars")
|
require.Equal(t, &Var2, val, "only structural identity is required for non-default vars")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user