func GenerateMergedJsonConfigMap()

in translator/cmdutil/translatorutil.go [108:220]


func GenerateMergedJsonConfigMap(ctx *context.Context) (map[string]interface{}, error) {
	// we use a map instead of an array here because we need to override the config value
	// for the append operation when the existing file name and new .tmp file name have diff
	// only for the ".tmp" suffix, i.e. it is override operation even it says append.
	var jsonConfigMapMap = make(map[string]map[string]interface{})

	if ctx.MultiConfig() == "append" || ctx.MultiConfig() == "remove" {
		// backwards compatible for the old json config file
		// this backwards compatible file can be treated as existing files
		jsonConfigMap, err := getJsonConfigMap(ctx.InputJsonFilePath(), ctx.Os())
		if err != nil {
			return nil, fmt.Errorf("unable to get old json config file with error: %v", err)
		}
		if jsonConfigMap != nil {
			jsonConfigMapMap[ctx.InputJsonFilePath()] = jsonConfigMap
		}
	}

	err := filepath.Walk(
		ctx.InputJsonDirPath(),
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				fmt.Printf("Cannot access %v: %v \n", path, err)
				return err
			}
			if envconfig.IsWindowsHostProcessContainer() {
				log.Printf("Skipping checking symbolic link for Windows host process containers %s. \n"+
					"These symbolic links are skipped as valuating symlinks is common failures for Windows containers", path)
			} else {
				if info.Mode()&os.ModeSymlink != 0 {
					log.Printf("Find symbolic link %s \n", path)
					path, err := filepath.EvalSymlinks(path)
					if err != nil {
						log.Printf("Symbolic link %v will be ignored due to err: %v. \n", path, err)
						return nil
					}
					info, err = os.Stat(path)
					if err != nil {
						log.Printf("Path %v will be ignored due to err: %v. \n", path, err)
					}
				}
				if info.IsDir() {
					return nil
				}
			}

			ext := filepath.Ext(path)
			if ext == constants.FileSuffixTmp {
				key := strings.TrimSuffix(path, constants.FileSuffixTmp)
				// .tmp files
				ext = filepath.Ext(key)
				// skip .yaml files
				if ext == constants.FileSuffixYAML {
					return nil
				}
				if ctx.MultiConfig() == "default" || ctx.MultiConfig() == "append" {
					jsonConfigMap, err := getJsonConfigMap(path, ctx.Os())
					if err != nil {
						return err
					}
					if jsonConfigMap != nil {
						jsonConfigMapMap[key] = jsonConfigMap
					}
				}
			} else if ext == constants.FileSuffixYAML {
				// skip .yaml files
				return nil
			} else {
				// non .tmp / existing files
				if ctx.MultiConfig() == "append" || ctx.MultiConfig() == "remove" {
					jsonConfigMap, err := getJsonConfigMap(path, ctx.Os())
					if err != nil {
						return err
					}
					if jsonConfigMap != nil {
						if _, ok := jsonConfigMapMap[path]; !ok {
							jsonConfigMapMap[path] = jsonConfigMap
						}
					}
				}
			}

			return nil
		})
	if err != nil {
		log.Printf("unable to scan config dir %v with error: %v", ctx.InputJsonDirPath(), err)
	}

	if len(jsonConfigMapMap) == 0 {
		// For containerized agent, try to read env variable only when json configuration file is absent
		if jsonConfigContent, ok := os.LookupEnv(config.CWConfigContent); ok && os.Getenv(config.RUN_IN_CONTAINER) == config.RUN_IN_CONTAINER_TRUE {
			log.Printf("Reading json config from from environment variable %v.", config.CWConfigContent)
			jm, err := translatorUtil.GetJsonMapFromJsonBytes([]byte(jsonConfigContent))
			if err != nil {
				return nil, fmt.Errorf("unable to get json map from environment variable %v with error: %v", config.CWConfigContent, err)
			}
			jsonConfigMapMap[config.CWConfigContent] = jm
		}
	}

	defaultConfig, err := translatorUtil.GetDefaultJsonConfigMap(ctx.Os(), ctx.Mode())
	if err != nil {
		return nil, err
	}
	mergedJsonConfigMap, err := jsonconfig.MergeJsonConfigMaps(jsonConfigMapMap, defaultConfig, ctx.MultiConfig())
	if err != nil {
		return nil, err
	}

	// Json Schema Validation by gojsonschema
	checkSchema(mergedJsonConfigMap)
	return mergedJsonConfigMap, nil
}