How to handle a 'dynamic' YAML configuration file

I have created an app that manipulates certain files present in specific folders, by moving them locally first, and after manipulation they are moved back to the folder of origin on the server.
The app is meant to run on multiple machines, each of them ‘monitoring’ a specific set of folders, some machine monitors just 1 folder, other 2 folders or more.
I am using a YAML configuration file to pass the path of each folder to monitor. The YAML file (config.yml) looks like this:

# This folder is used temporarily to perform the manipulation
processingfolder: C:\Processing\

# The server(s) folder(s), they are all mapped on the local computer, or use address
drives:
    # folder1
    folder1: F:\data\

    # folder2
    folder2: G:\data\

    # folder3
    folder3: H:\data\

To parse the configuration file I would do as follow:

package main

import (
	"io/ioutil"
	"os"

	"gopkg.in/yaml.v2"
)

//configuration from .yml file
type config struct {
	processingfolder string `yaml:"processingfolder"`
	drives           struct {
		folder1 string `yaml:"folder1"`
		folder2 string `yaml:"folder2"`
		folder3 string `yaml:"folder3"`
	} `yaml:"drives"`
}

func (c *config) getConf() *config {
	yamlFile, err := ioutil.ReadFile("./config.yml")
	if err != nil {
		//file does not exist
		os.Exit(1)
	}
	err = yaml.Unmarshal(yamlFile, c)
	if err != nil {
		//wrong format
		os.Exit(1)
	}

	if _, err := os.Stat(c.processingfolder); os.IsNotExist(err) {
		//it should exist tho
		os.Exit(1)
	}

	if _, err := os.Stat(c.drives.folder1); os.IsNotExist(err) {
		//does not exist, tell to check mapping
		os.Exit(1)
	}

	if _, err := os.Stat(c.drives.folder2); os.IsNotExist(err) {
		//does not exist, tell to check mapping
		os.Exit(1)
	}

	if _, err := os.Stat(c.drives.folder3); os.IsNotExist(err) {
		//does not exist, tell to check mapping
		os.Exit(1)
	}

	return c
}

func main() {
	var c config
	c.getConf()

	//do stuff here
}

Now it comes my problem. The app will be used by multiple machine, some will have to monitor just one folder, other will have to monitor 2 or more. The number of folder to monitor is not written in stone, and it will luckily change in from time to time. Also, it is not known what its the maximum number of folder a machine will have to monitor, maybe 10, maybe 20, maybe more. I could manually code the config struct to holds 30+ drives

type config struct {
	processingfolder string `yaml:"processingfolder"`
	drives           struct {
		folder1 string `yaml:"folder1"`
		folder2 string `yaml:"folder2"`
		//...
		//...
		folder30 string `yaml:"folder30"`
	} `yaml:"drives"`
}

and make the app using only the ones that are ‘specified’ in the YAML file, but that it not very elegant to do I think.
Is there a way to create the config struct dynamically?

Why not use collections in yaml-file? https://yaml.org/spec/1.2/spec.html#id2759963

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.