Skip to content

Instantly share code, notes, and snippets.

@atombender
Created March 18, 2020 03:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atombender/a196e8909b417c492797a37b8f5c4c64 to your computer and use it in GitHub Desktop.
Save atombender/a196e8909b417c492797a37b8f5c4c64 to your computer and use it in GitHub Desktop.
package config
import (
"fmt"
"io"
"io/ioutil"
"path/filepath"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
jaegercfg "github.com/uber/jaeger-client-go/config"
jaegerprom "github.com/uber/jaeger-lib/metrics/prometheus"
"gopkg.in/yaml.v2"
)
// Config is the top level record describing the config-file for a Gradient node
type Config struct {
DataStore *DataStore `yaml:"dataStore"`
SearchStore *SearchStore `yaml:"searchStore"`
Batch *Batch `yaml:"batch"`
EventBus *EventBus `yaml:"cluster"`
Security *Security `yaml:"security"`
Classes Classes `yaml:"classes"`
Limits Limits `yaml:"limits"`
HTTP HTTP `yaml:"http"`
GRPC GRPC `yaml:"grpc"`
Metrics Metrics `yaml:"metrics"`
Logging Logging `yaml:"logging"`
Components Components `yaml:"components"`
Jobs *Jobs `yaml:"jobs"`
ConfigReloadablePath string `yaml:"configReloadablePath"`
UnknownFields map[string]interface{} `yaml:",inline"`
}
// UnmarshalYAML implements yaml.Unmarshaler to intercept unknown keys.
func (cfg *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
type raw Config
var tmp raw
if err := unmarshal(&tmp); err != nil {
return err
}
for key := range tmp.UnknownFields {
return fmt.Errorf("Unknown key %q", key)
}
if tmp.Batch == nil {
tmp.Batch = &Batch{}
if err := tmp.Batch.UnmarshalYAML(noop); err != nil {
return err
}
}
*cfg = Config(tmp)
return nil
}
func (cfg *Config) NormalizePaths(relativeToPath string) {
if cfg.Security != nil {
cfg.Security.NormalizePaths(relativeToPath)
}
}
// Validate the entire config for a Gradient node
func (cfg *Config) Validate() error {
if cfg.EventBus != nil {
if err := cfg.EventBus.Validate(); err != nil {
return err
}
}
if cfg.DataStore != nil {
if err := cfg.DataStore.Validate(); err != nil {
return errors.Wrapf(err, "Data store configuration is not valid")
}
}
if err := cfg.HTTP.Validate(); err != nil {
return errors.Wrapf(err, "HTTP configuration not valid")
}
if cfg.SearchStore != nil {
if err := cfg.SearchStore.Validate(); err != nil {
return err
}
}
if cfg.Security != nil {
if err := cfg.Security.Validate(); err != nil {
return err
}
}
if cfg.Batch != nil {
if err := cfg.Batch.Validate(); err != nil {
return err
}
}
if cfg.Components != nil {
if err := cfg.Components.Validate(); err != nil {
return err
}
}
if cfg.Jobs != nil {
if err := cfg.Jobs.Validate(); err != nil {
return err
}
}
return nil
}
func (c *Config) InitTracer() (io.Closer, error) {
jcfg, err := jaegercfg.FromEnv()
if err != nil {
return nil, errors.Wrapf(err, "could not get Jaeger configuration: %w", err)
}
tracer, closer, err := jcfg.NewTracer(
// jaegercfg.Logger(jaegerzap.NewLogger(logger.Named("jaeger").Desugar())),
jaegercfg.Metrics(jaegerprom.New()),
)
if err != nil {
return nil, errors.Wrap(err, "could not initialize Jaeger tracer")
}
opentracing.SetGlobalTracer(tracer)
return closer, nil
}
// ConfigFromFile reads the config from a file(!)
func ConfigFromFile(fileName string) (*Config, error) {
b, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, errors.Wrapf(err, "Unable to read config file %q", fileName)
}
var config Config
if err := yaml.Unmarshal(b, &config); err != nil {
return nil, errors.Wrapf(err, "Unable to parse config file %q", fileName)
}
config.NormalizePaths(filepath.Dir(fileName))
if err := config.Validate(); err != nil {
return nil, errors.Wrap(err, "Configuration is not valid")
}
return &config, nil
}
// noop() is used to trigger UnmarshalYAML to set up default values
func noop(iface interface{}) error {
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment