diff --git a/ctrlz/topics/assets/assets.gen.go b/ctrlz/topics/assets/assets.gen.go index 9fcdc67c..0b7d76eb 100644 --- a/ctrlz/topics/assets/assets.gen.go +++ b/ctrlz/topics/assets/assets.gen.go @@ -239,6 +239,8 @@ var _templatesEnvHtml = []byte(`{{ define "content" }} Name Value + Default + Status @@ -247,6 +249,8 @@ var _templatesEnvHtml = []byte(`{{ define "content" }} {{.Name}} {{.Value}} + {{.DefaultValue}} + {{.FeatureStatus}} {{ end }} diff --git a/ctrlz/topics/assets/templates/env.html b/ctrlz/topics/assets/templates/env.html index 4569d3dc..e96a4dbe 100644 --- a/ctrlz/topics/assets/templates/env.html +++ b/ctrlz/topics/assets/templates/env.html @@ -9,6 +9,8 @@ Name Value + Default + Status @@ -17,6 +19,8 @@ {{.Name}} {{.Value}} + {{.DefaultValue}} + {{.FeatureStatus}} {{ end }} diff --git a/ctrlz/topics/env.go b/ctrlz/topics/env.go index 8f73bdb8..72161080 100644 --- a/ctrlz/topics/env.go +++ b/ctrlz/topics/env.go @@ -1,4 +1,4 @@ -// Copyright 2018 Istio Authors +/// Copyright 2018 Istio Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import ( "istio.io/pkg/ctrlz/fw" "istio.io/pkg/ctrlz/topics/assets" + "istio.io/pkg/env" ) type envTopic struct { @@ -42,20 +43,30 @@ func (envTopic) Prefix() string { } type envVar struct { - Name string `json:"name"` - Value string `json:"value"` + Name string `json:"name"` + Value string `json:"value"` + DefaultValue string `json:"defaultvalue"` + FeatureStatus string `json:"featurestatus"` } func getVars() []envVar { - env := os.Environ() - sort.Strings(env) + regEnv := env.VarDescriptions() + otherEnv := os.Environ() + sort.Strings(otherEnv) result := []envVar{} - for _, v := range env { + visited := make(map[string]bool, len(regEnv)) + for _, v := range regEnv { + visited[v.Name] = true + result = append(result, envVar{Name: v.Name, Value: v.GetGeneric(), DefaultValue: v.DefaultValue, FeatureStatus: v.FeatureStatus.String()}) + } + for _, v := range otherEnv { var eq = strings.Index(v, "=") var name = v[:eq] - var value = v[eq+1:] - result = append(result, envVar{Name: name, Value: value}) + if _, ok := visited[name]; !ok { + var value = v[eq+1:] + result = append(result, envVar{Name: name, Value: value, DefaultValue: "UNKNOWN", FeatureStatus: "UNKNOWN"}) + } } return result diff --git a/env/var.go b/env/var.go index dd06caf9..ad1db56a 100644 --- a/env/var.go +++ b/env/var.go @@ -17,6 +17,7 @@ package env import ( + "fmt" "os" "sort" "strconv" @@ -42,6 +43,27 @@ const ( DURATION ) +type FeatureStatus byte + +const ( + Alpha FeatureStatus = iota + Beta + Stable + Unknown +) + +func (s FeatureStatus) String() string { + switch s { + case Alpha: + return "Alpha" + case Beta: + return "Beta" + case Stable: + return "Stable" + } + return "Unknown" +} + // Var describes a single environment variable type Var struct { // The name of the environment variable. @@ -61,6 +83,9 @@ type Var struct { // The type of the variable's value Type VarType + + // The support level of the feature controlled by this env var + FeatureStatus FeatureStatus } // StringVar represents a single string environment variable. @@ -109,39 +134,49 @@ func VarDescriptions() []Var { // RegisterStringVar registers a new string environment variable. func RegisterStringVar(name string, defaultValue string, description string) StringVar { - v := Var{Name: name, DefaultValue: defaultValue, Description: description, Type: STRING} + v := Var{Name: name, DefaultValue: defaultValue, Description: description, Type: STRING, FeatureStatus: Unknown} RegisterVar(v) return StringVar{getVar(name)} } // RegisterBoolVar registers a new boolean environment variable. func RegisterBoolVar(name string, defaultValue bool, description string) BoolVar { - v := Var{Name: name, DefaultValue: strconv.FormatBool(defaultValue), Description: description, Type: BOOL} + v := Var{Name: name, DefaultValue: strconv.FormatBool(defaultValue), Description: description, Type: BOOL, FeatureStatus: Unknown} RegisterVar(v) return BoolVar{getVar(name)} } // RegisterIntVar registers a new integer environment variable. func RegisterIntVar(name string, defaultValue int, description string) IntVar { - v := Var{Name: name, DefaultValue: strconv.FormatInt(int64(defaultValue), 10), Description: description, Type: INT} + v := Var{Name: name, DefaultValue: strconv.FormatInt(int64(defaultValue), 10), Description: description, Type: INT, FeatureStatus: Unknown} RegisterVar(v) return IntVar{getVar(name)} } // RegisterFloatVar registers a new floating-point environment variable. func RegisterFloatVar(name string, defaultValue float64, description string) FloatVar { - v := Var{Name: name, DefaultValue: strconv.FormatFloat(defaultValue, 'G', -1, 64), Description: description, Type: FLOAT} + v := Var{Name: name, DefaultValue: strconv.FormatFloat(defaultValue, 'G', -1, 64), Description: description, Type: FLOAT, FeatureStatus: Unknown} RegisterVar(v) return FloatVar{v} } // RegisterDurationVar registers a new duration environment variable. func RegisterDurationVar(name string, defaultValue time.Duration, description string) DurationVar { - v := Var{Name: name, DefaultValue: defaultValue.String(), Description: description, Type: DURATION} + v := Var{Name: name, DefaultValue: defaultValue.String(), Description: description, Type: DURATION, FeatureStatus: Unknown} RegisterVar(v) return DurationVar{getVar(name)} } +func SetVarStatus(v Var, f FeatureStatus) { + if val, ok := allVars[v.Name]; ok { + val.FeatureStatus = f + allVars[v.Name] = val + } else { + v.FeatureStatus = f + RegisterVar(v) + } +} + // RegisterVar registers a generic environment variable. func RegisterVar(v Var) { mutex.Lock() @@ -169,6 +204,32 @@ func getVar(name string) Var { return result } +func (v Var) LookupGeneric() (string, bool) { + switch v.Type { + case STRING: + return StringVar{Var: v}.Lookup() + case INT: + val, found := IntVar{Var: v}.Lookup() + return strconv.Itoa(val), found + case BOOL: + val, found := BoolVar{Var: v}.Lookup() + return strconv.FormatBool(val), found + case FLOAT: + val, found := FloatVar{Var: v}.Lookup() + return strconv.FormatFloat(val, 'f', -1, 64), found + case DURATION: + val, found := DurationVar{Var: v}.Lookup() + return val.String(), found + default: + return fmt.Sprintf("type %T is not recognized", v), false + } +} + +func (v Var) GetGeneric() string { + val, _ := v.LookupGeneric() + return val +} + // Get retrieves the value of the environment variable. // It returns the value, which will be the default if the variable is not present. // To distinguish between an empty value and an unset value, use Lookup. diff --git a/env/var_test.go b/env/var_test.go index 5fd993f9..68d3b680 100644 --- a/env/var_test.go +++ b/env/var_test.go @@ -329,3 +329,32 @@ func TestDupes(t *testing.T) { t.Errorf("Expected 'XYZ', got '%s'", v.Description) } } + +func TestVar_GetGeneric(t *testing.T) { + type fields struct { + Var Var + Value string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "first", + fields: fields{ + Var: RegisterStringVar("test", "defaultval", "description").Var, + Value: "non-default", + }, + want: "non-default", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + os.Setenv(tt.fields.Var.Name, tt.fields.Value) + if got := tt.fields.Var.GetGeneric(); got != tt.want { + t.Errorf("GetGeneric() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go index ec8c0281..cf3c71c3 100644 --- a/ledger/ledger_test.go +++ b/ledger/ledger_test.go @@ -22,10 +22,9 @@ import ( "testing" "time" - "golang.org/x/sync/errgroup" - "github.com/google/uuid" "github.com/spaolacci/murmur3" + "golang.org/x/sync/errgroup" "gotest.tools/assert" ) diff --git a/ledger/trie_cache.go b/ledger/trie_cache.go index f1683533..0a507644 100644 --- a/ledger/trie_cache.go +++ b/ledger/trie_cache.go @@ -15,11 +15,10 @@ package ledger import ( + "sync" "time" "istio.io/pkg/cache" - - "sync" ) type cacheDB struct { diff --git a/viperconfig/viperconfig.go b/viperconfig/viperconfig.go index 380bd51e..0ff407d0 100644 --- a/viperconfig/viperconfig.go +++ b/viperconfig/viperconfig.go @@ -18,10 +18,9 @@ import ( "fmt" "os" - "github.com/spf13/viper" - "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/spf13/viper" ) // AddConfigFlag appends a persistent flag for retrieving Viper config, as well as an initializer