Пример #1
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()
}
Пример #2
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
}