Exemple #1
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{Raw: rules}
	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the path policy
	for _, pp := range p.Paths {
		// Strip the glob character if found
		if strings.HasSuffix(pp.Prefix, "*") {
			pp.Prefix = strings.TrimSuffix(pp.Prefix, "*")
			pp.Glob = true
		}

		// Check the policy is valid
		switch pp.Policy {
		case PathPolicyDeny:
		case PathPolicyRead:
		case PathPolicyWrite:
		case PathPolicySudo:
		default:
			return nil, fmt.Errorf("Invalid path policy: %#v", pp)
		}
	}
	return p, nil
}
Exemple #2
0
func LoadServices(root string) (d []Config, err error) {
	files, _ := filepath.Glob(root + "/*.hcl")
	for _, file := range files {
		data, err := readFile(file)
		if err != nil {
			return nil, err
		}

		var deploy ServiceFile
		err = hcl.Decode(&deploy, data)
		if err != nil {
			return nil, err
		}

		for i, service := range deploy.Services {
			for key, value := range service.RawArtifact {
				value["type"] = key
				deploy.Services[i].Artifact = value
			}
		}

		d = append(d, deploy.Services...)
	}
	return
}
Exemple #3
0
func applyConfigFile(options *Options, filePath string) error {
	filePath = expandHomeDir(filePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return err
	}

	fileString := []byte{}
	log.Printf("Loading config file at: %s", filePath)
	fileString, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	config := make(map[string]interface{})
	hcl.Decode(&config, string(fileString))
	o := structs.New(options)
	for _, name := range o.Names() {
		configName := strings.ToLower(strings.Join(camelcase.Split(name), "_"))
		if val, ok := config[configName]; ok {
			field, ok := o.FieldOk(name)
			if !ok {
				return errors.New("No such field: " + name)
			}
			err := field.Set(val)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
Exemple #4
0
//Load provides loading of configuration file
func Load(path string, item interface{}) error {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	switch checkPath(path) {
	case jsontype:
		err := json.Unmarshal([]byte(data), item)
		if err != nil {
			return err
		}

		return nil

	case yamltype:
		err := yaml.Unmarshal([]byte(data), item)
		if err != nil {
			return err
		}

		return nil

	case hcltype:
		err := hcl.Decode(item, string(data))
		if err != nil {
			return err
		}

		return nil
	default:
		return fmt.Errorf("Failed to load: This type is unknown")
	}
}
Exemple #5
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{}
	if rules == "" {
		// Hot path for empty rules
		return p, nil
	}

	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the key policy
	for _, kp := range p.Keys {
		switch kp.Policy {
		case KeyPolicyDeny:
		case KeyPolicyRead:
		case KeyPolicyWrite:
		default:
			return nil, fmt.Errorf("Invalid key policy: %#v", kp)
		}
	}

	// Validate the service policy
	for _, sp := range p.Services {
		switch sp.Policy {
		case ServicePolicyDeny:
		case ServicePolicyRead:
		case ServicePolicyWrite:
		default:
			return nil, fmt.Errorf("Invalid service policy: %#v", sp)
		}
	}

	// Validate the user event policies
	for _, ep := range p.Events {
		switch ep.Policy {
		case EventPolicyRead:
		case EventPolicyWrite:
		case EventPolicyDeny:
		default:
			return nil, fmt.Errorf("Invalid event policy: %#v", ep)
		}
	}

	// Validate the keyring policy
	switch p.Keyring {
	case KeyringPolicyRead:
	case KeyringPolicyWrite:
	case KeyringPolicyDeny:
	case "": // Special case to allow omitting the keyring policy
	default:
		return nil, fmt.Errorf("Invalid keyring policy: %#v", p.Keyring)
	}

	return p, nil
}
Exemple #6
0
func FromString(filename string, contents string) (*Config, error) {
	config := Config{}
	err := hcl.Decode(&config, contents)
	if err != nil {
		return nil, err
	}

	config.SourceFilename = filename
	return &config, nil
}
Exemple #7
0
func LoadTerraformConfig(path string) (*TerraformConfig, error) {
	var value TerraformConfig

	if _, err := os.Stat(path); err != nil {
		return nil, err
	}
	err := hcl.Decode(&value, readFile(path))
	if err != nil {
		return nil, err
	}
	return &value, nil
}
Exemple #8
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{}
	if rules == "" {
		// Hot path for empty rules
		return p, nil
	}

	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the key policy
	for _, kp := range p.Keys {
		if !isPolicyValid(kp.Policy) {
			return nil, fmt.Errorf("Invalid key policy: %#v", kp)
		}
	}

	// Validate the service policy
	for _, sp := range p.Services {
		if !isPolicyValid(sp.Policy) {
			return nil, fmt.Errorf("Invalid service policy: %#v", sp)
		}
	}

	// Validate the user event policies
	for _, ep := range p.Events {
		if !isPolicyValid(ep.Policy) {
			return nil, fmt.Errorf("Invalid event policy: %#v", ep)
		}
	}

	// Validate the prepared query policies
	for _, pq := range p.PreparedQueries {
		if !isPolicyValid(pq.Policy) {
			return nil, fmt.Errorf("Invalid query policy: %#v", pq)
		}
	}

	// Validate the keyring policy - this one is allowed to be empty
	if p.Keyring != "" && !isPolicyValid(p.Keyring) {
		return nil, fmt.Errorf("Invalid keyring policy: %#v", p.Keyring)
	}

	// Validate the operator policy - this one is allowed to be empty
	if p.Operator != "" && !isPolicyValid(p.Operator) {
		return nil, fmt.Errorf("Invalid operator policy: %#v", p.Operator)
	}

	return p, nil
}
Exemple #9
0
func LoadConfigFile(configFile string) Config {
	var conf Config

	configData, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Fatalf("Error: Couldn't read config file %s: %s", configFile, err)
	}

	err = hcl.Decode(&conf, string(configData))
	if err != nil {
		log.Fatalf("Error parsing config file %s: %s", configFile, err)
	}

	return conf
}
Exemple #10
0
func InitializeConfig() *Config {
	var cfg Config
	cfgData, err := ioutil.ReadFile(CfgFile)
	if err != nil {
		log.Fatalln("Unable to locate Config File. make sure you specify it using the --config flag")
		return nil
	}
	err = hcl.Decode(&cfg, string(cfgData))

	if err != nil {
		log.Fatalln("Unable to parse Config File.")
		return nil
	}

	return &cfg
}
Exemple #11
0
// parseVariableAsHCL parses the value of a single variable as would have been specified
// on the command line via -var or in an environment variable named TF_VAR_x, where x is
// the name of the variable. In order to get around the restriction of HCL requiring a
// top level object, we prepend a sentinel key, decode the user-specified value as its
// value and pull the value back out of the resulting map.
func parseVariableAsHCL(name string, input string, targetType config.VariableType) (interface{}, error) {
	// expecting a string so don't decode anything, just strip quotes
	if targetType == config.VariableTypeString {
		return strings.Trim(input, `"`), nil
	}

	// return empty types
	if strings.TrimSpace(input) == "" {
		switch targetType {
		case config.VariableTypeList:
			return []interface{}{}, nil
		case config.VariableTypeMap:
			return make(map[string]interface{}), nil
		}
	}

	const sentinelValue = "SENTINEL_TERRAFORM_VAR_OVERRIDE_KEY"
	inputWithSentinal := fmt.Sprintf("%s = %s", sentinelValue, input)

	var decoded map[string]interface{}
	err := hcl.Decode(&decoded, inputWithSentinal)
	if err != nil {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", name, input, err)
	}

	if len(decoded) != 1 {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", name, input)
	}

	parsedValue, ok := decoded[sentinelValue]
	if !ok {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
	}

	switch targetType {
	case config.VariableTypeList:
		return parsedValue, nil
	case config.VariableTypeMap:
		if list, ok := parsedValue.([]map[string]interface{}); ok {
			return list[0], nil
		}

		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
	default:
		panic(fmt.Errorf("unknown type %s", targetType.Printable()))
	}
}
Exemple #12
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{Raw: rules}
	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the path policy
	for _, pc := range p.Paths {
		// Strip the glob character if found
		if strings.HasSuffix(pc.Prefix, "*") {
			pc.Prefix = strings.TrimSuffix(pc.Prefix, "*")
			pc.Glob = true
		}

		// Map old-style policies into capabilities
		switch pc.Policy {
		case OldDenyPathPolicy:
			pc.Capabilities = []string{DenyCapability}
		case OldReadPathPolicy:
			pc.Capabilities = append(pc.Capabilities, []string{ReadCapability, ListCapability}...)
		case OldWritePathPolicy:
			pc.Capabilities = append(pc.Capabilities, []string{CreateCapability, ReadCapability, UpdateCapability, DeleteCapability, ListCapability}...)
		case OldSudoPathPolicy:
			pc.Capabilities = append(pc.Capabilities, []string{CreateCapability, ReadCapability, UpdateCapability, DeleteCapability, ListCapability, SudoCapability}...)
		}

		// Initialize the map
		pc.CapabilitiesBitmap = 0
		for _, cap := range pc.Capabilities {
			switch cap {
			// If it's deny, don't include any other capability
			case DenyCapability:
				pc.Capabilities = []string{DenyCapability}
				pc.CapabilitiesBitmap = DenyCapabilityInt
				goto PathFinished
			case CreateCapability, ReadCapability, UpdateCapability, DeleteCapability, ListCapability, SudoCapability:
				pc.CapabilitiesBitmap |= cap2Int[cap]
			default:
				return nil, fmt.Errorf("Invalid capability: %#v", pc)
			}
		}

	PathFinished:
	}
	return p, nil
}
Exemple #13
0
func applyConfigFile(options *Options, filePath string) error {
	filePath = ExpandHomeDir(filePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return err
	}

	fileString := []byte{}
	log.Printf("Loading config file at: %s", filePath)
	fileString, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	config := make(map[string]interface{})
	hcl.Decode(&config, string(fileString))
	o := structs.New(options)
	for _, name := range o.Names() {
		configName := strings.ToLower(strings.Join(camelcase.Split(name), "_"))
		if val, ok := config[configName]; ok {
			field, ok := o.FieldOk(name)
			if !ok {
				return errors.New("No such option: " + name)
			}

			var err error
			if name == "Preferences" {
				prefs := val.([]map[string]interface{})[0]
				htermPrefs := make(map[string]interface{})
				for key, value := range prefs {
					htermPrefs[strings.Replace(key, "_", "-", -1)] = value
				}
				err = field.Set(htermPrefs)
			} else {
				err = field.Set(val)
			}

			if err != nil {
				return err
			}

		}
	}

	return nil
}
Exemple #14
0
func initConfig() Config {
	var configPath = os.Getenv("HOME")
	var c Config
	var err error

	config, err := ioutil.ReadFile(filepath.Join(configPath, configFile))
	if err != nil {
		log.Printf("Error parsing config: %s", err)
		configUsage()
	}

	err = hcl.Decode(&c, string(config))
	if err != nil {
		log.Fatalf("Configuration decode error: %s", err)
	}

	return c
}
Exemple #15
0
func readConfig() *Config {
	bts, err := ioutil.ReadFile(Path())

	if err != nil {
		printer.SayErr("Could not read %s", Path())
		os.Exit(1)
	}

	var cfg *Config
	defaults := DefaultConfig()

	err = hcl.Decode(&cfg, string(bts[:]))

	if err != nil {
		printer.SayErr("[dcdr] config parse error %+v", err)
		os.Exit(1)
	}

	if cfg.Namespace == "" {
		cfg.Namespace = defaults.Namespace
	}

	if cfg.Username == "" {
		cfg.Username = defaults.Username
	}

	if cfg.Watcher.OutputPath == "" {
		cfg.Watcher.OutputPath = defaults.Watcher.OutputPath
	}

	if cfg.Server.Host == "" {
		cfg.Server.Host = defaults.Server.Host
	}

	if cfg.Server.Endpoint == "" {
		cfg.Server.Endpoint = defaults.Server.Endpoint
	}

	if cfg.Server.JSONRoot == "" {
		cfg.Server.JSONRoot = defaults.Server.JSONRoot
	}

	return cfg
}
Exemple #16
0
func ApplyConfigFile(options *Options, filePath string) error {
	filePath = ExpandHomeDir(filePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return err
	}

	fileString := []byte{}
	log.Printf("Loading config file at: %s", filePath)
	fileString, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	if err := hcl.Decode(options, string(fileString)); err != nil {
		return err
	}

	return nil
}
Exemple #17
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{Raw: rules}
	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the path policy
	for _, pp := range p.Paths {
		switch pp.Policy {
		case PathPolicyDeny:
		case PathPolicyRead:
		case PathPolicyWrite:
		case PathPolicySudo:
		default:
			return nil, fmt.Errorf("Invalid path policy: %#v", pp)
		}
	}
	return p, nil
}
Exemple #18
0
func loadProfileFile(options *Options) (map[string]interface{}, error) {
	prefString := []byte{}
	prefPath := options.ProfileFile
	if options.ProfileFile == DefaultOptions.ProfileFile {
		prefPath = os.Getenv("HOME") + "/.gotty.prf"
	}
	if _, err := os.Stat(prefPath); os.IsNotExist(err) {
		if options.ProfileFile != DefaultOptions.ProfileFile {
			return nil, err
		}
	} else {
		log.Printf("Loading profile path: %s", prefPath)
		prefString, _ = ioutil.ReadFile(prefPath)
	}
	var prefMap map[string]interface{}
	err := hcl.Decode(&prefMap, string(prefString))
	if err != nil {
		return nil, err
	}
	return prefMap, nil
}
Exemple #19
0
func main() {
	configFile := flag.String("config", "terf.conf", "path to the terf configuration file")
	configProfile := flag.String("profile", "development", "configuration profile to use")
	flag.Parse()

	// Load the configuration file.
	var config Config
	p, err := ioutil.ReadFile(*configFile)
	if err != nil {
		glog.Fatalln("failed to read config file:", err)
	}
	if err := hcl.Decode(&config, string(p)); err != nil {
		glog.Fatalln("failed to decode config file:", err)
	}
	profile, ok := config[*configProfile]
	if !ok {
		glog.Fatalf("no such config profile %q", *configProfile)
	}

	glog.Infoln("connecting to database")

	tplGlob := filepath.Join(profile.Terf.TemplateDir, "*.html")
	glog.Infof("loading templates %q", tplGlob)
	Templates, err = template.ParseGlob(tplGlob)
	if err != nil {
		glog.Fatalln(err)
	}

	http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir(profile.Terf.StaticDir))))
	http.HandleFunc("/", handleIndex)

	glog.Infoln("listening on", profile.Terf.ListenAddr)
	if err := http.ListenAndServe(profile.Terf.ListenAddr, nil); err != nil {
		glog.Fatalln(err)
	}
	glog.Infoln("terminated gracefully")
}
func (cp ConfigParser) UpdateConfig(hclText string, result *Config) error {
	var tmp Config
	tmp = *result
	if err := hcl.Decode(&tmp, hclText); err != nil {
		return err
	}

	if tmp.InfluxDB.CheckLapse == 0 {
		tmp.InfluxDB.CheckLapse = DefaultConfig.InfluxDB.CheckLapse
	}

	if cp.AllowDNS && tmp.MesosDNS != nil {
		resolver := NewDNSResolver(&tmp)
		if err := resolver.resolve(); err != nil {
			return err
		}

	}

	log.Printf("%+v\n", tmp)
	*result = tmp

	return nil
}
Exemple #21
0
// parseVariableAsHCL parses the value of a single variable as would have been specified
// on the command line via -var or in an environment variable named TF_VAR_x, where x is
// the name of the variable. In order to get around the restriction of HCL requiring a
// top level object, we prepend a sentinel key, decode the user-specified value as its
// value and pull the value back out of the resulting map.
func parseVariableAsHCL(name string, input interface{}, targetType config.VariableType) (interface{}, error) {
	if targetType == config.VariableTypeString {
		return input, nil
	}

	const sentinelValue = "SENTINEL_TERRAFORM_VAR_OVERRIDE_KEY"
	inputWithSentinal := fmt.Sprintf("%s = %s", sentinelValue, input)

	var decoded map[string]interface{}
	err := hcl.Decode(&decoded, inputWithSentinal)
	if err != nil {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", name, input, err)
	}

	if len(decoded) != 1 {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", name, input)
	}

	parsedValue, ok := decoded[sentinelValue]
	if !ok {
		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
	}

	switch targetType {
	case config.VariableTypeList:
		return parsedValue, nil
	case config.VariableTypeMap:
		if list, ok := parsedValue.([]map[string]interface{}); ok {
			return list[0], nil
		}

		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
	default:
		panic(fmt.Errorf("unknown type %s", targetType))
	}
}
Exemple #22
0
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func Parse(rules string) (*Policy, error) {
	// Decode the rules
	p := &Policy{}
	if rules == "" {
		// Hot path for empty rules
		return p, nil
	}

	if err := hcl.Decode(p, rules); err != nil {
		return nil, fmt.Errorf("Failed to parse ACL rules: %v", err)
	}

	// Validate the key policy
	for _, kp := range p.Keys {
		switch kp.Policy {
		case KeyPolicyDeny:
		case KeyPolicyRead:
		case KeyPolicyWrite:
		default:
			return nil, fmt.Errorf("Invalid key policy: %#v", kp)
		}
	}
	return p, nil
}
Exemple #23
0
// ParseConfig reads the configuration file at the given path and returns a new
// Config struct with the data populated.
func ParseConfig(path string) (*Config, error) {
	var errs *multierror.Error

	// Read the contents of the file
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("error reading config at %q: %s", path, err)
	}

	// Parse the file (could be HCL or JSON)
	var shadow interface{}
	if err := hcl.Decode(&shadow, string(contents)); err != nil {
		return nil, fmt.Errorf("error decoding config at %q: %s", path, err)
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("error converting config at %q", path)
	}
	flattenKeys(parsed, []string{"auth", "ssl", "syslog", "vault", "deduplicate"})

	// Create a new, empty config
	config := new(Config)

	// Use mapstructure to populate the basic config fields
	metadata := new(mapstructure.Metadata)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			watch.StringToWaitDurationHookFunc(),
			mapstructure.StringToSliceHookFunc(","),
			mapstructure.StringToTimeDurationHookFunc(),
		),
		ErrorUnused: true,
		Metadata:    metadata,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}
	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Store a reference to the path where this config was read from
	config.Path = path

	// Ensure there's a default value for the template's file permissions
	for _, t := range config.ConfigTemplates {
		if t.Perms == 0000 {
			t.Perms = defaultFilePerms
		}
	}

	// Update the list of set keys
	if config.setKeys == nil {
		config.setKeys = make(map[string]struct{})
	}
	for _, key := range metadata.Keys {
		if _, ok := config.setKeys[key]; !ok {
			config.setKeys[key] = struct{}{}
		}
	}
	config.setKeys["path"] = struct{}{}

	d := DefaultConfig()
	d.Merge(config)
	config = d

	return config, errs.ErrorOrNil()
}
Exemple #24
0
// ParseConfig reads the configuration file at the given path and returns a new
// Config struct with the data populated.
func ParseConfig(path string) (*Config, error) {
	var errs *multierror.Error

	// Read the contents of the file
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("error reading config at %q: %s", path, err)
	}

	// Parse the file (could be HCL or JSON)
	var shadow interface{}
	if err := hcl.Decode(&shadow, string(contents)); err != nil {
		return nil, fmt.Errorf("error decoding config at %q: %s", path, err)
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("error converting config at %q", path)
	}
	flattenKeys(parsed, []string{"auth", "ssl", "syslog"})

	// Parse the prefixes
	if raw, ok := parsed["prefixes"]; ok {
		if typed, ok := raw.([]interface{}); !ok {
			err = fmt.Errorf("error converting prefixes to []interface{} at %q, was %T", path, raw)
			errs = multierror.Append(errs, err)
			delete(parsed, "prefixes")
		} else {
			prefixes := make([]*dep.StoreKeyPrefix, 0, len(typed))
			for _, p := range typed {
				if s, ok := p.(string); ok {
					if prefix, err := dep.ParseStoreKeyPrefix(s); err != nil {
						err = fmt.Errorf("error parsing prefix %q at %q: %s", p, path, err)
						errs = multierror.Append(errs, err)
					} else {
						prefixes = append(prefixes, prefix)
					}
				} else {
					err = fmt.Errorf("error converting %T to string", p)
					errs = multierror.Append(errs, err)
					delete(parsed, "prefixes")
				}
			}
			parsed["prefixes"] = prefixes
		}
	}

	// Parse the wait component
	if raw, ok := parsed["wait"]; ok {
		if typed, ok := raw.(string); !ok {
			err = fmt.Errorf("error converting wait to string at %q", path)
			errs = multierror.Append(errs, err)
			delete(parsed, "wait")
		} else {
			if wait, err := watch.ParseWait(typed); err != nil {
				err = fmt.Errorf("error parsing wait at %q: %s", path, err)
				errs = multierror.Append(errs, err)
				delete(parsed, "wait")
			} else {
				parsed["wait"] = map[string]time.Duration{
					"min": wait.Min,
					"max": wait.Max,
				}
			}
		}
	}

	// Create a new, empty config
	config := new(Config)

	// Use mapstructure to populate the basic config fields
	metadata := new(mapstructure.Metadata)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			mapstructure.StringToSliceHookFunc(","),
			mapstructure.StringToTimeDurationHookFunc(),
		),
		ErrorUnused: true,
		Metadata:    metadata,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}
	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Store a reference to the path where this config was read from
	config.Path = path

	// Update the list of set keys
	if config.setKeys == nil {
		config.setKeys = make(map[string]struct{})
	}
	for _, key := range metadata.Keys {
		if _, ok := config.setKeys[key]; !ok {
			config.setKeys[key] = struct{}{}
		}
	}
	config.setKeys["path"] = struct{}{}

	d := DefaultConfig()
	d.Merge(config)
	config = d

	return config, errs.ErrorOrNil()
}
Exemple #25
0
// ParseConfig reads the configuration file at the given path and returns a new
// Config struct with the data populated.
func ParseConfig(path string) (*Config, error) {
	var errs *multierror.Error

	// Read the contents of the file
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Parse the file (could be HCL or JSON)
	var parsed interface{}
	if err := hcl.Decode(&parsed, string(contents)); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Create a new, empty config
	config := &Config{}

	// Use mapstructure to populate the basic config fields
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		ErrorUnused: true,
		Metadata:    nil,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Store a reference to the path where this config was read from
	config.Path = path

	// Parse the prefix sources
	for _, prefix := range config.Prefixes {
		parsed, err := dep.ParseStoreKeyPrefix(prefix.SourceRaw)
		if err != nil {
			errs = multierror.Append(errs, err)
			continue
		}
		prefix.Source = parsed

		// If no destination was given, default to the prefix
		if prefix.Destination == "" {
			prefix.Destination = parsed.Prefix
		}
	}

	// Parse the MaxStale component
	if raw := config.MaxStaleRaw; raw != "" {
		stale, err := time.ParseDuration(raw)

		if err == nil {
			config.MaxStale = stale
		} else {
			errs = multierror.Append(errs, fmt.Errorf("max_stale invalid: %v", err))
		}
	}

	// Extract the last Auth block
	if len(config.AuthRaw) > 0 {
		config.Auth = config.AuthRaw[len(config.AuthRaw)-1]
	}

	// Extract the last SSL block
	if len(config.SSLRaw) > 0 {
		config.SSL = config.SSLRaw[len(config.SSLRaw)-1]
	}

	// Extract the last Syslog block
	if len(config.SyslogRaw) > 0 {
		config.Syslog = config.SyslogRaw[len(config.SyslogRaw)-1]
	}

	// Parse the Retry component
	if raw := config.RetryRaw; raw != "" {
		retry, err := time.ParseDuration(raw)

		if err == nil {
			config.Retry = retry
		} else {
			errs = multierror.Append(errs, fmt.Errorf("retry invalid: %v", err))
		}
	}

	// Parse the Wait component
	if raw := config.WaitRaw; raw != "" {
		wait, err := watch.ParseWait(raw)

		if err == nil {
			config.Wait = wait
		} else {
			errs = multierror.Append(errs, fmt.Errorf("wait invalid: %v", err))
		}
	}

	return config, errs.ErrorOrNil()
}
Exemple #26
0
// ParseConfig reads the configuration file at the given path and returns a new
// Config struct with the data populated.
func ParseConfig(path string) (*Config, error) {
	var errs *multierror.Error

	// Read the contents of the file
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("error reading config at %q: %s", path, err)
	}

	// Parse the file (could be HCL or JSON)
	var shadow interface{}
	if err := hcl.Decode(&shadow, string(contents)); err != nil {
		return nil, fmt.Errorf("error decoding config at %q: %s", path, err)
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("error converting config at %q", path)
	}
	flattenKeys(parsed, []string{"auth", "ssl", "syslog", "vault"})

	//
	if raw, ok := parsed["max_stale"]; ok {
		if typed, ok := raw.(string); !ok {
			err = fmt.Errorf("error converting max_stale to string at %q", path)
			errs = multierror.Append(errs, err)
			delete(parsed, "max_stale")
		} else {
			if stale, err := time.ParseDuration(typed); err != nil {
				err = fmt.Errorf("error parsing max_stale at %q: %s", path, err)
				errs = multierror.Append(errs, err)
				delete(parsed, "max_stale")
			} else {
				parsed["max_stale"] = stale
			}
		}
	}

	if raw, ok := parsed["retry"]; ok {
		if typed, ok := raw.(string); !ok {
			err = fmt.Errorf("error converting retry to string at %q", path)
			errs = multierror.Append(errs, err)
			delete(parsed, "retry")
		} else {
			if stale, err := time.ParseDuration(typed); err != nil {
				err = fmt.Errorf("error parsing retry at %q: %s", path, err)
				errs = multierror.Append(errs, err)
				delete(parsed, "retry")
			} else {
				parsed["retry"] = stale
			}
		}
	}

	if raw, ok := parsed["wait"]; ok {
		if typed, ok := raw.(string); !ok {
			err = fmt.Errorf("error converting wait to string at %q", path)
			errs = multierror.Append(errs, err)
			delete(parsed, "wait")
		} else {
			if wait, err := watch.ParseWait(typed); err != nil {
				err = fmt.Errorf("error parsing wait at %q: %s", path, err)
				errs = multierror.Append(errs, err)
				delete(parsed, "wait")
			} else {
				parsed["wait"] = map[string]time.Duration{
					"min": wait.Min,
					"max": wait.Max,
				}
			}
		}
	}

	// Create a new, empty config
	config := new(Config)

	// Use mapstructure to populate the basic config fields
	metadata := new(mapstructure.Metadata)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		ErrorUnused: true,
		Metadata:    metadata,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}
	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Store a reference to the path where this config was read from
	config.Path = path

	// Update the list of set keys
	if config.setKeys == nil {
		config.setKeys = make(map[string]struct{})
	}
	for _, key := range metadata.Keys {
		if _, ok := config.setKeys[key]; !ok {
			config.setKeys[key] = struct{}{}
		}
	}
	config.setKeys["path"] = struct{}{}

	d := DefaultConfig()
	d.Merge(config)
	config = d

	return config, errs.ErrorOrNil()
}
Exemple #27
0
// Parse parses the given string contents as a config
func Parse(s string) (*Config, error) {
	var errs *multierror.Error

	// Parse the file (could be HCL or JSON)
	var shadow interface{}
	if err := hcl.Decode(&shadow, s); err != nil {
		return nil, fmt.Errorf("error decoding config: %s", err)
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("error converting config")
	}
	flattenKeys(parsed, []string{
		"auth",
		"ssl",
		"syslog",
		"exec",
		"vault",
		"deduplicate",
	})

	// Deprecations
	if vault, ok := parsed["vault"].(map[string]interface{}); ok {
		if val, ok := vault["renew"]; ok {
			log.Println(`[WARN] vault.renew has been renamed to vault.renew_token. ` +
				`Update your configuration files and change "renew" to "renew_token".`)
			vault["renew_token"] = val
			delete(vault, "renew")
		}
	}

	// Create a new, empty config
	config := new(Config)

	// Use mapstructure to populate the basic config fields
	metadata := new(mapstructure.Metadata)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			StringToFileModeFunc(),
			signals.StringToSignalFunc(),
			watch.StringToWaitDurationHookFunc(),
			mapstructure.StringToSliceHookFunc(","),
			mapstructure.StringToTimeDurationHookFunc(),
		),
		ErrorUnused: true,
		Metadata:    metadata,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}
	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Explicitly check for the nil signal and set the value back to nil
	if config.ReloadSignal == signals.SIGNIL {
		config.ReloadSignal = nil
	}
	if config.DumpSignal == signals.SIGNIL {
		config.DumpSignal = nil
	}
	if config.KillSignal == signals.SIGNIL {
		config.KillSignal = nil
	}
	if config.Exec != nil {
		if config.Exec.ReloadSignal == signals.SIGNIL {
			config.Exec.ReloadSignal = nil
		}
		if config.Exec.KillSignal == signals.SIGNIL {
			config.Exec.KillSignal = nil
		}
	}

	// Setup default values for templates
	for _, t := range config.ConfigTemplates {
		// Ensure there's a default value for the template's file permissions
		if t.Perms == 0000 {
			t.Perms = DefaultFilePerms
		}

		// Ensure we have a default command timeout
		if t.CommandTimeout == 0 {
			t.CommandTimeout = DefaultCommandTimeout
		}

		// Set up a default zero wait, which disables it for this
		// template.
		if t.Wait == nil {
			t.Wait = &watch.Wait{}
		}
	}

	// Update the list of set keys
	if config.setKeys == nil {
		config.setKeys = make(map[string]struct{})
	}
	for _, key := range metadata.Keys {
		if _, ok := config.setKeys[key]; !ok {
			config.setKeys[key] = struct{}{}
		}
	}
	config.setKeys["path"] = struct{}{}

	d := DefaultConfig()
	d.Merge(config)
	config = d

	return config, errs.ErrorOrNil()
}
Exemple #28
0
// Parse parses the given string contents as a config
func Parse(s string) (*Config, error) {
	var shadow interface{}
	if err := hcl.Decode(&shadow, s); err != nil {
		return nil, errors.Wrap(err, "error decoding config")
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, errors.New("error converting config")
	}

	flattenKeys(parsed, []string{
		"auth",
		"consul",
		"consul.auth",
		"consul.retry",
		"consul.ssl",
		"deduplicate",
		"env",
		"exec",
		"exec.env",
		"ssl",
		"syslog",
		"vault",
		"vault.retry",
		"vault.ssl",
		"wait",
	})

	// FlattenFlatten keys belonging to the templates. We cannot do this above
	// because it is an array of tmeplates.
	if templates, ok := parsed["template"].([]map[string]interface{}); ok {
		for _, template := range templates {
			flattenKeys(template, []string{
				"env",
				"exec",
				"exec.env",
				"wait",
			})
		}
	}

	// TODO: Deprecations
	if vault, ok := parsed["vault"].(map[string]interface{}); ok {
		if val, ok := vault["renew"]; ok {
			log.Println(`[WARN] vault.renew has been renamed to vault.renew_token. ` +
				`Update your configuration files and change "renew" to "renew_token".`)
			vault["renew_token"] = val
			delete(vault, "renew")
		}
	}

	if auth, ok := parsed["auth"].(map[string]interface{}); ok {
		log.Println("[WARN] auth has been moved under the consul stanza. " +
			"Update your configuration files and place auth inside consul { }.")
		if _, ok := parsed["consul"]; !ok {
			parsed["consul"] = make(map[string]interface{})
		}
		parsed["consul"].(map[string]interface{})["auth"] = auth
		delete(parsed, "auth")
	}

	if retry, ok := parsed["retry"].(string); ok {
		log.Println("[WARN] retry has been moved under the consul stanza. " +
			"Update your configuration files and place retry inside consul { }.")
		if _, ok := parsed["consul"]; !ok {
			parsed["consul"] = make(map[string]interface{})
		}
		parsed["consul"].(map[string]interface{})["retry"] = map[string]interface{}{
			"backoff": retry,
		}
		delete(parsed, "retry")
	}

	if ssl, ok := parsed["ssl"].(map[string]interface{}); ok {
		log.Println("[WARN] ssl has been moved under the consul stanza. " +
			"Update your configuration files and place ssl inside consul { }.")
		if _, ok := parsed["consul"]; !ok {
			parsed["consul"] = make(map[string]interface{})
		}
		parsed["consul"].(map[string]interface{})["ssl"] = ssl
		delete(parsed, "ssl")
	}

	if token, ok := parsed["token"].(string); ok {
		log.Println("[WARN] token has been moved under the consul stanza. " +
			"Update your configuration files and place token inside consul { }.")
		if _, ok := parsed["consul"]; !ok {
			parsed["consul"] = make(map[string]interface{})
		}
		parsed["consul"].(map[string]interface{})["token"] = token
		delete(parsed, "token")
	}

	// Create a new, empty config
	var c Config

	// Use mapstructure to populate the basic config fields
	var md mapstructure.Metadata
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			ConsulStringToStructFunc(),
			StringToFileModeFunc(),
			signals.StringToSignalFunc(),
			StringToWaitDurationHookFunc(),
			mapstructure.StringToSliceHookFunc(","),
			mapstructure.StringToTimeDurationHookFunc(),
		),
		ErrorUnused: true,
		Metadata:    &md,
		Result:      &c,
	})
	if err != nil {
		return nil, errors.Wrap(err, "mapstructure decoder creation failed")
	}
	if err := decoder.Decode(parsed); err != nil {
		return nil, errors.Wrap(err, "mapstructure decode failed")
	}

	return &c, nil
}
Exemple #29
0
// ParseConfig reads the configuration file at the given path and returns a new
// Config struct with the data populated.
func ParseConfig(path string) (*Config, error) {
	var errs *multierror.Error

	// Read the contents of the file
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("error reading config at %q: %s", path, err)
	}

	// Parse the file (could be HCL or JSON)
	var shadow interface{}
	if err := hcl.Decode(&shadow, string(contents)); err != nil {
		return nil, fmt.Errorf("error decoding config at %q: %s", path, err)
	}

	// Convert to a map and flatten the keys we want to flatten
	parsed, ok := shadow.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("error converting config at %q", path)
	}
	flattenKeys(parsed, []string{"auth", "ssl", "syslog", "vault"})

	// Create a new, empty config
	config := new(Config)

	// Use mapstructure to populate the basic config fields
	metadata := new(mapstructure.Metadata)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			watch.StringToWaitDurationHookFunc(),
			mapstructure.StringToSliceHookFunc(","),
			mapstructure.StringToTimeDurationHookFunc(),
		),
		ErrorUnused: true,
		Metadata:    metadata,
		Result:      config,
	})
	if err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}
	if err := decoder.Decode(parsed); err != nil {
		errs = multierror.Append(errs, err)
		return nil, errs.ErrorOrNil()
	}

	// Store a reference to the path where this config was read from
	config.Path = path

	// Handle deprecations
	if len(config.PrefixesOld) > 0 {
		log.Printf(`[WARN] Specifying the key "prefixes" in the configuration is `+
			`no longer supported. Please specify each prefix individually using `+
			`the key "prefix" (config at %s)`, path)
		prefixes := make([]*ConfigPrefix, 0, len(config.PrefixesOld))
		for _, prefix := range config.PrefixesOld {
			prefixes = append(prefixes, &ConfigPrefix{
				Path: prefix,
			})
		}
		config.Prefixes = append(prefixes, config.Prefixes...)
		config.PrefixesOld = nil
	}

	// Update the list of set keys
	if config.setKeys == nil {
		config.setKeys = make(map[string]struct{})
	}
	for _, key := range metadata.Keys {
		if _, ok := config.setKeys[key]; !ok {
			config.setKeys[key] = struct{}{}
		}
	}
	config.setKeys["path"] = struct{}{}

	d := DefaultConfig()
	d.Merge(config)
	config = d

	return config, errs.ErrorOrNil()
}
Exemple #30
0
func (hclParser *HCLParser) Parse(content []byte, c map[string]interface{}) error {
	return hcl.Decode(&c, string(content))
}