config: error on invalid configuration

Since the default led priority is no longer 'Blink', the priority now
has to be explicitly defined when using either group priority or led
priority.

If a configuration does not define the priority, the configuration is
invalid and in the yaml case, phosphor-led-manager should fail to build,
in the json case, the process should exit due to the configuration
error.

The config validation has been extracted into it's own file and made
separate from json config parsing.

So every config will go through the same validation even if its been
created via yaml.

Change-Id: Ifda65942b0768d6c0d3b25076f7a1236b46b3d9f
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/scripts/parse_led.py b/scripts/parse_led.py
index eac764c..5724e6d 100755
--- a/scripts/parse_led.py
+++ b/scripts/parse_led.py
@@ -6,16 +6,30 @@
 from inflection import underscore
 
 
-def check_led_priority(led_name, value, priority_dict):
+def config_error(ofile, led_name, group_name, message):
+    ofile.close()
+    os.remove(ofile.name)
+    raise ValueError(
+        "Invalid Configuration for LED ["
+        + led_name
+        + "] in Group ["
+        + group_name
+        + "]: "
+        + message
+    )
+
+
+def check_led_priority(led_name, group, value, priority_dict):
 
     if led_name in priority_dict:
         if value != priority_dict[led_name]:
             # Priority for a particular LED needs to stay SAME
             # across all groups
-            ofile.close()
-            os.remove(ofile.name)
-            raise ValueError(
-                "Priority for [" + led_name + "] is NOT same across all groups"
+            config_error(
+                ofile,
+                led_name,
+                group,
+                "Priority is NOT same across all groups",
             )
     else:
         priority_dict[led_name] = value
@@ -23,20 +37,41 @@
     return 0
 
 
-def generate_file_single_led(ifile, led_name, list_dict, priority_dict, ofile):
+def led_action_literal(action):
+    if action == "":
+        return "std::nullopt"
 
-    value = list_dict.get("Priority")
+    return "phosphor::led::Layout::Action::" + str(action)
 
-    check_led_priority(led_name, value, priority_dict)
 
-    action = "phosphor::led::Layout::Action::" + str(
-        list_dict.get("Action", "Off")
-    )
+def generate_file_single_led(
+    ifile, led_name, list_dict, priority_dict, ofile, has_group_priority, group
+):
+
+    has_led_priority = "Priority" in list_dict
+
+    if has_group_priority and has_led_priority:
+        config_error(
+            ofile,
+            led_name,
+            group,
+            "cannot mix group priority with led priority",
+        )
+
+    if (not has_group_priority) and (not has_led_priority):
+        config_error(
+            ofile, led_name, group, "no group priority or led priority defined"
+        )
+
+    led_priority = list_dict.get("Priority", "")
+
+    if has_led_priority:
+        check_led_priority(led_name, group, led_priority, priority_dict)
+
+    action = led_action_literal(list_dict.get("Action", "Off"))
     dutyOn = str(list_dict.get("DutyOn", 50))
     period = str(list_dict.get("Period", 0))
-    priority = "phosphor::led::Layout::Action::" + str(
-        list_dict.get("Priority", "Blink")
-    )
+    priority = led_action_literal(led_priority)
 
     ofile.write('        {"' + underscore(led_name) + '",')
     ofile.write(action + ",")
@@ -75,7 +110,13 @@
 
     for led_name, list_dict in list(led_dict.items()):
         generate_file_single_led(
-            ifile, led_name, list_dict, priority_dict, ofile
+            ifile,
+            led_name,
+            list_dict,
+            priority_dict,
+            ofile,
+            has_group_priority,
+            group,
         )
 
     ofile.write("   }}},\n")