[libvirt-ci PATCH v2 06/13] lcitool: Introduce methods to load and validate the YAML config

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch introduce a set of class Config helper methods in order to
parse and validate the new global YAML config.
Currently, only 'install' and 'gitlab' sections are recognized with
the flavor setting defaulting to "test" (backwards compatibility) and
gitlab runner registration url defaulting to "https://gitlab.com";; the
rest of the options are currently mandatory.

Signed-off-by: Erik Skultety <eskultet@xxxxxxxxxx>
---
 guests/lcitool | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/guests/lcitool b/guests/lcitool
index 5b44582..577e9d2 100755
--- a/guests/lcitool
+++ b/guests/lcitool
@@ -128,6 +128,30 @@ class Util:
 
 class Config:
 
+    def __init__(self):
+
+        # Load the template config containing the defaults first, this must
+        # always succeed.
+        # NOTE: we should load this from /usr/share once we start packaging
+        # lcitool
+        base = Util.get_base()
+        with open(os.path.join(base, "config.yaml"), "r") as fp:
+            self.values = yaml.safe_load(fp)
+
+        try:
+            with open(self._get_config_file("config.yaml"), "r") as fp:
+                user_config = yaml.safe_load(fp)
+        except Exception as e:
+            raise Exception("Missing or invalid config.yaml file: {}".format(e))
+
+        if user_config is None:
+            raise Exception("Missing or invalid config.yaml file")
+
+        # Validate the user provided config and use it to override the default
+        # settings
+        self._validate(user_config)
+        self._update(user_config)
+
     @staticmethod
     def _get_config_file(name):
         try:
@@ -149,6 +173,64 @@ class Config:
 
         return os.path.join(config_dir, name)
 
+    @staticmethod
+    def _remove_unknown_keys(_dict, known_keys):
+        keys = list(_dict.keys())
+
+        for k in keys:
+            if k not in known_keys:
+                del _dict[k]
+
+    def _validate_section(self, config, section, mandatory_keys):
+        # remove keys we don't recognize
+        self._remove_unknown_keys(config[section], self.values[section].keys())
+
+        # check that the mandatory keys are present and non-empty
+        for key in mandatory_keys:
+            if config.get(section).get(key, None) is None:
+                raise Exception(("Missing or empty value for mandatory key"
+                                 "'{}.{}'").format(section, key))
+
+        # check that all keys have values assigned and of the right type
+        for key in config[section].keys():
+
+            # mandatory keys were already checked, so this covers optional keys
+            if config[section][key] is None:
+                raise Exception(
+                    "Missing value for '{}.{}'".format(section, key)
+                )
+
+            if not isinstance(config[section][key], (str, int)):
+                raise Exception(
+                    "Invalid type for key '{}.{}'".format(section, key)
+                )
+
+    def _validate(self, config):
+        # delete sections we don't recognize
+        self._remove_unknown_keys(config, self.values.keys())
+
+        if "install" not in config:
+            raise Exception("Missing mandatory section 'install'")
+
+        self._validate_section(config, "install", ["root_password"])
+
+        # we only need this for the gitlab check below, if 'flavor' is missing
+        # that's okay, we'll provide a default later
+        flavor = config["install"].get("flavor", None)
+        if flavor is not None and flavor not in ["test", "jenkins", "gitlab"]:
+            raise Exception(
+                "Invalid value '{}' for 'install.flavor'".format(flavor)
+            )
+
+        if flavor == "gitlab":
+            self._validate_section(config, "gitlab", ["runner_secret"])
+
+    def _update(self, values):
+        self.values["install"].update(values["install"])
+
+        if values.get("gitlab", None):
+            self.values["gitlab"].update(values["gitlab"])
+
     def get_flavor(self):
         flavor_file = self._get_config_file("flavor")
 
-- 
2.25.3




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux