Skip to content

Commit f21e136

Browse files
committed
PoC of profiles support
1 parent 1971d30 commit f21e136

File tree

8 files changed

+158
-0
lines changed

8 files changed

+158
-0
lines changed

fmf/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import fmf.context
1616
import fmf.utils as utils
1717
from fmf.utils import dict_to_yaml, log
18+
from fmf.profile import Profile
1819

1920
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2021
# Constants
@@ -794,3 +795,7 @@ def __getitem__(self, key):
794795
return self.children[key[1:]]
795796
else:
796797
return self.data[key]
798+
799+
def apply_profile(self, profile: Profile) -> None:
800+
profile.apply_rule(self)
801+

fmf/profile.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from copy import deepcopy
2+
from fmf.context import Context
3+
#from fmf.base import Tree
4+
"""
5+
generic _definition/:
6+
where: a is defined and b is defined
7+
key1: value1 # override
8+
key2+: value2 # append
9+
key3-: value3 # remove
10+
key4?: value4 # define if not defined
11+
12+
plan_definition/:
13+
where: execute is defined and discovery is defined
14+
15+
# append to prepare phase
16+
prepare+:
17+
name: some name
18+
how: shell
19+
script: systemctl start httpd
20+
# create reporting if not defined
21+
report?:
22+
how: html
23+
open: true
24+
25+
# override provision by own definition
26+
provision:
27+
how: virtual
28+
image: fedora-37
29+
30+
31+
32+
"""
33+
34+
35+
class ProfileError(Exception):
36+
pass
37+
38+
39+
class ProfileWithoutWhereStatement(ProfileError):
40+
pass
41+
42+
43+
class Profile:
44+
45+
def __init__(self, rule: dict, name = None):
46+
self._raw_rule = rule
47+
self.name = name
48+
if "where" not in self._raw_rule.keys():
49+
raise ProfileWithoutWhereStatement
50+
self.where = self._raw_rule.pop("where")
51+
self.rules = deepcopy(self._raw_rule)
52+
53+
def _check_if_fmf_node_match(self, node):
54+
context = Context(**node.data)
55+
return context.matches(self.where)
56+
57+
def _apply_rule(self, node):
58+
59+
if not self._check_if_fmf_node_match(node):
60+
return
61+
for rule in self.rules:
62+
if isinstance(rule, str) and rule.endswith("?"):
63+
rule_clear = rule[:-1]
64+
data = {rule_clear : self.rules[rule]}
65+
if rule_clear in node.data:
66+
# do not override if defined
67+
continue
68+
else:
69+
data = {rule: self.rules[rule]}
70+
node._merge_special(node.data, data)
71+
72+
def apply_rule(self, node):
73+
for item in node.climb():
74+
self._apply_rule(item)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
plan1_definition:
2+
where: execute is defined cc and discover is defined
3+
# append to prepare phase
4+
prepare+:
5+
name: some name
6+
how: shell
7+
script: systemctl start httpd
8+
# create reporting if not defined
9+
report?:
10+
how: html
11+
open: true
12+
13+
# override provision by own definition
14+
provision:
15+
how: virtual
16+
image: fedora-37
17+
18+
19+
test1_definition:
20+
where: summary is defined and discovery is defined
21+
new_attribute: hello world
22+
test+: appended
23+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

tests/unit/data/profile/tree/main.fmf

Whitespace-only changes.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/base:
2+
summary: test plans
3+
execute:
4+
how: tmt
5+
provision:
6+
how: minute
7+
/plan0:
8+
discover:
9+
how: fmf
10+
/plan1:
11+
discover:
12+
how: shell
13+
report:
14+
how: polarion
15+
prepare:
16+
name: some name
17+
how: shell
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
test: test1.sh
2+
summary: hello

tests/unit/test_profile.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from unittest import TestCase
2+
from pathlib import Path
3+
4+
import yaml
5+
6+
from fmf import Tree
7+
from fmf.profile import Profile
8+
9+
PROFILE_PATH = Path(__file__).parent / "data" / "profile"
10+
PROFILE = PROFILE_PATH / "profile_file.yaml"
11+
12+
class ProfileLoad(TestCase):
13+
def setUp(self) -> None:
14+
with PROFILE.open("r") as profile_file:
15+
self.profile_data = yaml.safe_load(profile_file)
16+
17+
def test_load(self):
18+
profiles = []
19+
for k, v in self.profile_data.items():
20+
profiles.append(Profile(v, name=k))
21+
22+
23+
class ProfileApply(TestCase):
24+
def setUp(self) -> None:
25+
with PROFILE.open("r") as profile_file:
26+
self.profile_data = yaml.safe_load(profile_file)
27+
self.profiles = []
28+
for k, v in self.profile_data.items():
29+
self.profiles.append(Profile(v, name=k))
30+
self.fmf_tree = Tree(PROFILE_PATH / "tree")
31+
32+
def test_apply_to_test(self):
33+
for profile in self.profiles:
34+
self.fmf_tree.apply_profile(profile)
35+
for item in self.fmf_tree.climb():
36+
print(item.data)

0 commit comments

Comments
 (0)