Skip to content

Commit

Permalink
Bind env variables with ENV-BINDER, clean tests
Browse files Browse the repository at this point in the history
Thanks to ENV-BINDER we have moved the responsibility for bindings of environment variables to an external, well tested package.

ENV-BINDER works with unexported fields, so we can bind the values of some fields and calculate a new value from them in the calculation phase.
An example is enum, where env_variable has the value "info" but the internal state of the structure has the value 1. (I have also created a
PR in [kelsyhightower/envconfig](kelseyhightower/envconfig#198), which solves the problem with private fields).

Thanks to the delegation of responsibility I could delete about a third of the test without changing the depressolver
 coverage, which increased to 95% with the changes.

Signed-off-by: kuritka <[email protected]>
  • Loading branch information
kuritka committed Oct 22, 2021
1 parent 999def5 commit ed91365
Show file tree
Hide file tree
Showing 5 changed files with 564 additions and 521 deletions.
52 changes: 30 additions & 22 deletions controllers/depresolver/depresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,62 +80,70 @@ const (
type Log struct {
// Level [panic, fatal, error,warn,info,debug,trace], defines level of logger, default: info
Level zerolog.Level
// Format [simple,json] specifies how the logger prints values
// Format [simple,json] specifies how the logger prints values;
Format LogFormat
// NoColor prints colored output if Format == simple
NoColor bool
NoColor bool `env:"NO_COLOR, default=false"`
// format is binding source for Format
format string `env:"LOG_FORMAT, default=simple"`
// level is binding source for Level
level string `env:"LOG_LEVEL, default=info"`
}

// Infoblox configuration
type Infoblox struct {
// Host
Host string
Host string `env:"INFOBLOX_GRID_HOST"`
// Version
Version string
Version string `env:"INFOBLOX_WAPI_VERSION"`
// Port
Port int
Port int `env:"INFOBLOX_WAPI_PORT, default=0"`
// Username
Username string
Username string `env:"EXTERNAL_DNS_INFOBLOX_WAPI_USERNAME"`
// Password
Password string
// HTTPRequestTimeout seconds; default = 20
HTTPRequestTimeout int
// HTTPPoolConnections seconds; default = 10
HTTPPoolConnections int
Password string `env:"EXTERNAL_DNS_INFOBLOX_WAPI_PASSWORD"`
// HTTPRequestTimeout seconds
HTTPRequestTimeout int `env:"INFOBLOX_HTTP_REQUEST_TIMEOUT, default=20"`
// HTTPPoolConnections seconds
HTTPPoolConnections int `env:"INFOBLOX_HTTP_POOL_CONNECTIONS, default=10"`
}

// Config is operator configuration returned by depResolver
type Config struct {
// Reschedule of Reconcile loop to pickup external Gslb targets
ReconcileRequeueSeconds int
ReconcileRequeueSeconds int `env:"RECONCILE_REQUEUE_SECONDS, default=30"`
// ClusterGeoTag to determine specific location
ClusterGeoTag string
ClusterGeoTag string `env:"CLUSTER_GEO_TAG"`
// ExtClustersGeoTags to identify clusters in other locations in format separated by comma. i.e.: "eu,uk,us"
ExtClustersGeoTags []string
ExtClustersGeoTags []string `env:"EXT_GSLB_CLUSTERS_GEO_TAGS, default=[]"`
// EdgeDNSType is READONLY and is set automatically by configuration
EdgeDNSType EdgeDNSType
// EdgeDNSServers
EdgeDNSServers utils.DNSList
// to avoid breaking changes is used as fallback server for EdgeDNSServers
fallbackEdgeDNSServerName string `env:"EDGE_DNS_SERVER"`
// to avoid breaking changes is used as fallback server port for EdgeDNSServers
fallbackEdgeDNSServerPort int `env:"EDGE_DNS_SERVER_PORT, default=53"`
// EdgeDNSZone main zone which would contain gslb zone to delegate; e.g. example.com
EdgeDNSZone string
EdgeDNSZone string `env:"EDGE_DNS_ZONE"`
// DNSZone controlled by gslb; e.g. cloud.example.com
DNSZone string
DNSZone string `env:"DNS_ZONE"`
// K8gbNamespace k8gb namespace
K8gbNamespace string
K8gbNamespace string `env:"POD_NAMESPACE"`
// Infoblox configuration
Infoblox Infoblox
// CoreDNSExposed flag
CoreDNSExposed bool
CoreDNSExposed bool `env:"COREDNS_EXPOSED, default=false"`
// Log configuration
Log Log
// MetricsAddress in format address:port where address can be empty, IP address, or hostname, default: 0.0.0.0:8080
MetricsAddress string
MetricsAddress string `env:"METRICS_ADDRESS, default=0.0.0.0:8080"`
// route53Enabled hidden. EdgeDNSType defines all enabled Enabled types
route53Enabled bool
route53Enabled bool `env:"ROUTE53_ENABLED, default=false"`
// ns1Enabled flag
ns1Enabled bool
ns1Enabled bool `env:"NS1_ENABLED, default=false"`
// SplitBrainCheck flag decides whether split brain TXT records will be stored in edge DNS
SplitBrainCheck bool
SplitBrainCheck bool `env:"SPLIT_BRAIN_CHECK, default=false"`
}

// DependencyResolver resolves configuration for GSLB
Expand Down
53 changes: 21 additions & 32 deletions controllers/depresolver/depresolver_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import (
"strconv"
"strings"

"github.com/AbsaOSS/gopkg/env"
"github.com/AbsaOSS/env-binder/env"

"github.com/AbsaOSS/k8gb/controllers/internal/utils"
"github.com/rs/zerolog"
)
Expand Down Expand Up @@ -70,32 +71,24 @@ const (
func (dr *DependencyResolver) ResolveOperatorConfig() (*Config, error) {
var recognizedDNSTypes []EdgeDNSType
dr.onceConfig.Do(func() {

dr.config = &Config{}
dr.config.ReconcileRequeueSeconds, _ = env.GetEnvAsIntOrFallback(ReconcileRequeueSecondsKey, 30)
dr.config.ClusterGeoTag = env.GetEnvAsStringOrFallback(ClusterGeoTagKey, "")
dr.config.ExtClustersGeoTags = env.GetEnvAsArrayOfStringsOrFallback(ExtClustersGeoTagsKey, []string{})
dr.config.route53Enabled = env.GetEnvAsBoolOrFallback(Route53EnabledKey, false)
dr.config.ns1Enabled = env.GetEnvAsBoolOrFallback(NS1EnabledKey, false)
dr.config.CoreDNSExposed = env.GetEnvAsBoolOrFallback(CoreDNSExposedKey, false)
dr.config.EdgeDNSServers = parseEdgeDNSServers(env.GetEnvAsStringOrFallback(EdgeDNSServersKey,
fmt.Sprintf("%s:%v", env.GetEnvAsStringOrFallback(EdgeDNSServerKey, ""),
env.GetEnvAsStringOrFallback(EdgeDNSServerPortKey, "53"))))
dr.config.EdgeDNSZone = env.GetEnvAsStringOrFallback(EdgeDNSZoneKey, "")
dr.config.DNSZone = env.GetEnvAsStringOrFallback(DNSZoneKey, "")
dr.config.K8gbNamespace = env.GetEnvAsStringOrFallback(K8gbNamespaceKey, "")
dr.config.Infoblox.Host = env.GetEnvAsStringOrFallback(InfobloxGridHostKey, "")
dr.config.Infoblox.Version = env.GetEnvAsStringOrFallback(InfobloxVersionKey, "")
dr.config.Infoblox.Port, _ = env.GetEnvAsIntOrFallback(InfobloxPortKey, 0)
dr.config.Infoblox.Username = env.GetEnvAsStringOrFallback(InfobloxUsernameKey, "")
dr.config.Infoblox.Password = env.GetEnvAsStringOrFallback(InfobloxPasswordKey, "")
dr.config.Infoblox.HTTPPoolConnections, _ = env.GetEnvAsIntOrFallback(InfobloxHTTPPoolConnectionsKey, 10)
dr.config.Infoblox.HTTPRequestTimeout, _ = env.GetEnvAsIntOrFallback(InfobloxHTTPRequestTimeoutKey, 20)
dr.config.Log.Level, _ = zerolog.ParseLevel(strings.ToLower(env.GetEnvAsStringOrFallback(LogLevelKey, zerolog.InfoLevel.String())))
dr.config.Log.Format = parseLogOutputFormat(strings.ToLower(env.GetEnvAsStringOrFallback(LogFormatKey, SimpleFormat.String())))
dr.config.Log.NoColor = env.GetEnvAsBoolOrFallback(LogNoColorKey, false)
dr.config.MetricsAddress = env.GetEnvAsStringOrFallback(MetricsAddressKey, "0.0.0.0:8080")
dr.config.SplitBrainCheck = env.GetEnvAsBoolOrFallback(SplitBrainCheckKey, false)

// binding
dr.errorConfig = env.Bind(dr.config)
if dr.errorConfig != nil {
return
}

// calculation
fallbackDNS := fmt.Sprintf("%s:%v", dr.config.fallbackEdgeDNSServerName, dr.config.fallbackEdgeDNSServerPort)
edgeDNSServerList := env.GetEnvAsArrayOfStringsOrFallback(EdgeDNSServersKey, []string{fallbackDNS})
dr.config.EdgeDNSServers = parseEdgeDNSServers(edgeDNSServerList)
dr.config.Log.Level, _ = zerolog.ParseLevel(strings.ToLower(dr.config.Log.level))
dr.config.Log.Format = parseLogOutputFormat(strings.ToLower(dr.config.Log.format))
dr.config.EdgeDNSType, recognizedDNSTypes = getEdgeDNSType(dr.config)

// validation
dr.errorConfig = dr.validateConfig(dr.config, recognizedDNSTypes)
})
return dr.config, dr.errorConfig
Expand Down Expand Up @@ -296,15 +289,11 @@ func parseMetricsAddr(metricsAddr string) (host string, port int, err error) {
return
}

func parseEdgeDNSServers(serverList string) []utils.DNSServer {
r := []utils.DNSServer{}
if len(strings.TrimSpace(serverList)) == 0 {
return r
}
chunks := strings.Split(serverList, ",")
func parseEdgeDNSServers(serverList []string) (r []utils.DNSServer) {
r = []utils.DNSServer{}
var host, portStr string
var err error
for _, chunk := range chunks {
for _, chunk := range serverList {
chunk = strings.TrimSpace(chunk)
switch strings.Count(chunk, ":") {
case 0: // ipv4 or domain w/o port
Expand Down
Loading

0 comments on commit ed91365

Please sign in to comment.