Example #1
0
File: config.go Project: nak3/nomad
// 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()
}
Example #2
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()
}
Example #3
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()
}