]> git.ipfire.org Git - nitsi.git/blob - src/nitsi/recipe.py
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