Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC of profiles support #196

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions fmf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import fmf.context
import fmf.utils as utils
from fmf.utils import dict_to_yaml, log
from fmf.profile import Profile

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Constants
Expand Down Expand Up @@ -794,3 +795,7 @@ def __getitem__(self, key):
return self.children[key[1:]]
else:
return self.data[key]

def apply_profile(self, profile: Profile) -> None:
profile.apply_rule(self)

44 changes: 44 additions & 0 deletions fmf/profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from copy import deepcopy
from fmf.context import Context
#from fmf.base import Tree

class ProfileError(Exception):
pass


class ProfileWithoutWhereStatement(ProfileError):
pass


class Profile:

def __init__(self, rule: dict, name = None):
self._raw_rule = rule
self.name = name
if "where" not in self._raw_rule.keys():
raise ProfileWithoutWhereStatement
self.where = self._raw_rule.pop("where")
self.rules = deepcopy(self._raw_rule)

def _check_if_fmf_node_match(self, node):
context = Context(**node.data)
return context.matches(self.where)

def _apply_rule(self, node):

if not self._check_if_fmf_node_match(node):
return
for rule in self.rules:
if isinstance(rule, str) and rule.endswith("?"):
rule_clear = rule[:-1]
data = {rule_clear : self.rules[rule]}
if rule_clear in node.data:
# do not override if defined
continue
else:
data = {rule: self.rules[rule]}
node._merge_special(node.data, data)

def apply_rule(self, node):
for item in node.climb():
self._apply_rule(item)
23 changes: 23 additions & 0 deletions tests/unit/data/profile/profile_file.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plan1_definition:
where: execute is defined cc and discover is defined
# append to prepare phase
prepare+:
name: some name
how: shell
script: systemctl start httpd
# create reporting if not defined
report?:
how: html
open: true

# override provision by own definition
provision:
how: virtual
image: fedora-37


test1_definition:
where: summary is defined and test is defined
new_attribute: hello world
test+: appended

1 change: 1 addition & 0 deletions tests/unit/data/profile/tree/.fmf/version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
17 changes: 17 additions & 0 deletions tests/unit/data/profile/tree/plan.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/base:
summary: test plans
execute:
how: tmt
provision:
how: minute
/plan0:
discover:
how: fmf
/plan1:
discover:
how: shell
report:
how: polarion
prepare:
name: some name
how: shell
2 changes: 2 additions & 0 deletions tests/unit/data/profile/tree/test.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test: test1.sh
summary: hello
36 changes: 36 additions & 0 deletions tests/unit/test_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from unittest import TestCase
from pathlib import Path

import yaml

from fmf import Tree
from fmf.profile import Profile

PROFILE_PATH = Path(__file__).parent / "data" / "profile"
PROFILE = PROFILE_PATH / "profile_file.yaml"

class ProfileLoad(TestCase):
def setUp(self) -> None:
with PROFILE.open("r") as profile_file:
self.profile_data = yaml.safe_load(profile_file)

def test_load(self):
profiles = []
for k, v in self.profile_data.items():
profiles.append(Profile(v, name=k))


class ProfileApply(TestCase):
def setUp(self) -> None:
with PROFILE.open("r") as profile_file:
self.profile_data = yaml.safe_load(profile_file)
self.profiles = []
for k, v in self.profile_data.items():
self.profiles.append(Profile(v, name=k))
self.fmf_tree = Tree(PROFILE_PATH / "tree")

def test_apply_to_test(self):
for profile in self.profiles:
self.fmf_tree.apply_profile(profile)
for item in self.fmf_tree.climb():
print(item.data)