func mergeCustomConfigs()

in agent/envoy_bootstrap/envoy_bootstrap.go [1284:1361]


func mergeCustomConfigs(bootYaml []byte, fileUtil FileUtil) ([]byte, error) {
	// Merge any custom configs specified via env variable without any protobuf validations
	bootConfig := make(map[string]interface{})
	if bootYaml != nil {
		if err := yaml.Unmarshal(bootYaml, &bootConfig); err != nil {
			return nil, err
		}
	}

	envVariables := [...]string{
		"ENVOY_TRACING_CFG_FILE",     // tracing
		"ENVOY_STATS_CONFIG_FILE",    // stats
		"ENVOY_STATS_SINKS_CFG_FILE", // stats sinks
	}

	for _, envVar := range envVariables {
		if v := env.Get(envVar); v != "" {
			log.Infof("%s is defined as %s, merging it with the envoy config.", envVar, v)

			data, err := fileUtil.Read(v)
			if err != nil {
				return nil, err
			}
			var customConfig map[string]interface{}
			if err := yaml.Unmarshal(data, &customConfig); err != nil {
				return nil, fmt.Errorf("failure to parse %s %s for the reason: %w", envVar, v, err)
			}
			if len(customConfig) == 0 {
				return nil, fmt.Errorf("Specified %s %s is empty.", envVar, v)
			}
			// We have found some users putting unrelated configs in these files, so we
			// best treat it like generic envoy config.
			bootConfig, err = mergeCustomConfigMaps(bootConfig, customConfig)
			if err != nil {
				return nil, fmt.Errorf("failure to merge %s %s into envoy config for the reason: %w", envVar, v, err)
			}

			// Any special handling are done in below switch statement
			switch envVar {
			case "ENVOY_STATS_SINKS_CFG_FILE":
				// TODO: Does it make sense to always error here?
				if _, ok := bootConfig[statsSinksKey]; !ok {
					return nil, fmt.Errorf("%s was specified as %s, but contained no valid stats_sinks configuration.", envVar, v)
				}
			}
		}
	}

	// Check if explicit resources are supplied via ENVOY_RESOURCES_CONFIG_FILE
	// This block doesn't have to be inside the above 'for' loop since we treat missing config differently. But
	// TODO: if you feel like this can be inside the 'for' loop feel free move it in: always 'less code' ==> 'less bugs'.
	envVar := "ENVOY_RESOURCES_CONFIG_FILE"
	if v := env.Get(envVar); v != "" {
		log.Infof("Explicitly appending supplied Envoy resources %s %s.", envVar, v)
		data, err := fileUtil.Read(v)
		if err != nil {
			return nil, err
		}
		var resourcesConfig map[string]interface{}
		if err := yaml.Unmarshal(data, &resourcesConfig); err != nil {
			return nil, fmt.Errorf("failure to parse %s %s for the reason: %w", envVar, v, err)
		}
		if len(resourcesConfig) == 0 {
			log.Warnf("Specified %s %s is empty, but will ignore and continue.", envVar, v)
		} else {
			bootConfig, err = mergeCustomConfigMaps(bootConfig, resourcesConfig)
			if err != nil {
				return nil, fmt.Errorf("failure to merge %s %s into envoy config for the reason: %w", envVar, v, err)
			}
		}
	}

	bootYaml, err := yaml.Marshal(bootConfig)
	if err != nil {
		return nil, err
	}
	return bootYaml, nil
}