Fix syntax and variable name in logging
[nitsi.git] / src / nitsi / recipe.py
1 #!/usr/bin/python3
2
3 import logging
4 import os
5
6 logger = logging.getLogger("nitsi.recipe")
7
8
9
10 class RecipeExeption(Exception):
11     def __init__(self, message):
12         self.message = message
13
14
15
16 # Should read the test, check if the syntax are valid
17 # and return tuples with the ( host, command ) structure
18 class recipe():
19     def __init__(self, path, circle=[]):
20         self.recipe_file = path
21         try:
22             self.path = os.path.dirname(self.recipe_file)
23             self.name = os.path.basename(self.path)
24         except BaseException as e:
25             logger.error("Failed to get the name of the test to this recipe")
26             raise e
27
28         self.log = logger.getChild(self.name)
29         self.log.debug("Path of recipe is: {}".format(self.recipe_file))
30         self._recipe = None
31         self._machines = None
32
33         self.in_recursion = True
34         if len(circle) == 0:
35             self.in_recursion = False
36
37         self.circle = circle
38         self.log.debug("Recipes we have already included: {}".format(self.circle))
39
40         if not os.path.isfile(self.recipe_file):
41             self.log.error("{} is not a file".format(self.recipe_file))
42             raise RecipeExeption("{} is not a file".format(self.recipe_file))
43
44         try:
45             with open(self.recipe_file) as fobj:
46                 self.raw_recipe = fobj.readlines()
47         except FileNotFoundError as error:
48             self.log.error("No such file: {}".format(self.recipe_file))
49             raise error
50
51     @property
52     def recipe(self):
53         if not self._recipe:
54             self.parse()
55
56         return self._recipe
57
58     @property
59     def machines(self):
60         if not self._machines:
61             self._machines = []
62             for line in self._recipe:
63                 if line[0] != "all" and line[0] not in self._machines:
64                     self._machines.append(line[0])
65
66         return self._machines
67
68     def parse(self):
69         self._recipe = []
70         i = 1
71         for line in self.raw_recipe:
72             raw_line = line.split(":", 1)
73             if len(raw_line) < 2:
74                 self.log.error("Error parsing the recipe in line {}".format(i))
75                 raise RecipeExeption("Error parsing the recipe in line {}".format(i))
76             cmd = raw_line[1].strip()
77             raw_line = raw_line[0].strip().split(" ")
78             if len(raw_line) == 0:
79                 self.log.error("Failed to parse the recipe in line {}".format(i))
80                 raise RecipeExeption("Failed to parse the recipe in line {}".format(i))
81
82             if raw_line[0].strip() == "":
83                     self.log.error("Failed to parse the recipe in line {}".format(i))
84                     raise RecipeExeption("Failed to parse the recipe in line {}".format(i))
85
86             machine = raw_line[0].strip()
87
88             if len(raw_line) == 2:
89                 extra = raw_line[1].strip()
90             else:
91                 extra = ""
92
93             # We could get a machine here or a include statement
94             if machine == "include":
95                 path = cmd.strip()
96                 path = os.path.normpath(self.path + "/" + path)
97                 path = path + "/recipe"
98                 if path in self.circle:
99                     self.log.error("Detect import loop!")
100                     raise RecipeExeption("Detect import loop!")
101                 self.circle.append(path)
102                 recipe_to_include = recipe(path, circle=self.circle)
103
104             if machine == "include":
105                 self._recipe.extend(recipe_to_include.recipe)
106             else:
107                 # Support also something like 'alice,bob: echo'
108                 machines = machine.split(",")
109                 for machine in machines:
110                     self._recipe.append((machine.strip(), extra.strip(), cmd.strip()))
111             i = i + 1
112
113             if not self.in_recursion:
114                 tmp_recipe = []
115                 for line in self._recipe:
116                     if line[0] != "all":
117                         tmp_recipe.append(line)
118                     else:
119                         for machine in self.machines:
120                             tmp_recipe.append((machine.strip(), line[1], line[2]))
121
122                 self._recipe = tmp_recipe