Rule Using Existing Parser and Combiner¶
Determine rule logic¶
The most effective way to get started in developing a rule is first to identify the problem you want to address.
For the purposes of this tutorial we’ll look at a very simple scenario. Sometimes when
researching an issue one of the things that we might need to know is which Red Hat OS the
host is running. For simplicity sake, in this example we will concentrate only on
determining if the red hat release is Fedora
.
For this case there is one thing we need to check:
Is the Red Hat release
Fedora
:
Identify Parsers¶
We can check Red Hat Release using the
RedhatRelease
parser.
Develop Plugin¶
Now that we have identified the required parsers, let’s get started on developing our plugin.
Create a file called is_fedora.py
in a Python package called tutorial
.
(env)[userone@hostone ~]$ cd ~/work/insights-core-tutorials/mycomponents/rules
(env)[userone@hostone rules]$ touch is_fedora.py
Open is_fedora.py
in your text editor of choice and start by stubbing out
the rule function and imports.
1 from insights.parsers.redhat_release import RedhatRelease
2 from insights import rule, make_fail, make_pass
3
4 @rule(RedhatRelease)
5 def report(rhrel):
6 pass
Let’s go over each line and describe the details:
1 from insights.parsers.redhat_release import RedhatRelease
Parsers you want to use must be imported. You must pass the parser class
objects directly to the @rule
decorator to declare them as dependencies for
your rule.
2 from insights import rule, make_fail, make_pass
rule
is a function decorator used to specify your main plugin function.
Combiners have a set of optional dependencies that are specified via the
requires
kwarg.
make_fail, make_pass
are formatting functions used to format
the return value of a rule function.
6 ERROR_KEY_IS_FEDORA = "IS_FEDORA"
7
8 CONTENT = {
9 ERROR_KEY_IS_FEDORA: "This machine ({{hostname}}) runs {{product}}.",
10 }
Here we define the Jinja2
template for message to be displayed for either
response tag
12 @rule(RedhatRelease)
Here we are specifying that this rule requires the output of the
insights.parsers.redhat_release.RedhatRelease
,
Now let’s add the rule logic
12 @rule(RedhatRelease, content=CONTENT)
13 def report(rhrel):
14 """Fires if the machine is running Fedora."""
15
16 if "Fedora" in rel.product:
17 return make_pass(ERROR_KEY_IS_FEDORA, hostname=hostname.hostname, product=rel.product)
18 else:
19 return make_fail(ERROR_KEY_IS_FEDORA, hostname=hostname.hostname, product=rel.product)
Now lets look at what the rule is doing.
The RedhatRelease
parser parses content from the /etc/redhat-release
file on the
host it is running on and returns an object containing the Red Hat OS information for the
host.
16 if "Fedora" in rhrel.product:
17 return make_pass(ERROR_KEY_IS_FEDORA, hostname=hostname.hostname, product=rel.product)
18 else:
19 return make_fail(ERROR_KEY_IS_FEDORA, hostname=hostname.hostname, product=rel.product)
Here we check to see if the value Fedora
is in the “product” property of the
“rhrel” object. If true then the rule returns a response telling us that the host
is indeed running Fedora
, along with the product information returned by the
parser. If false then the rule returns a response telling us that the host is
not running Fedora
, along with the product information returned by the parser.
Develop Tests¶
Start out by creating a test_is_fedora.py
module in a tests
package.
(env)[userone@hostone ~]$ cd ~/work/insights-core-tutorials/tests/rules
(env)[userone@hostone rules]$ touch __init__.py
(env)[userone@hostone rules]$ touch test_is_fedora.py
Open test_is_fedora.py
in your text editor of choice and start by stubbing
out a test and the required imports.
1 from .. import is_fedora
2 from insights.specs import Specs
3 from insights.tests import InputData, archive_provider
4 from insights.core.plugins import make_fail, make_pass
5
6
7 @archive_provider(is_fedora.report)
8 def integration_test():
9 pass
The framework provides an integration test framework that allows you to define
an InputData
object filled with raw examples of files required by your rule
and an expected response. The object is evaluated by the pipeline as it would
be in a production context, after which the response is compared to your
expected output.
The @archive_provider
decorator registers your test function with the
framework. This function must be a generator that yields InputData
and an
expected response in a two tuple. The @archive_provider
decorator takes
one parameter, the rule function to test.
The bulk of the work in building a test for a rule is in defining the
InputData
object. If you remember our rule we accept RedhatRelease
.
We will define a data snippet for each test.
FEDORA = "Fedora release 28 (Twenty Eight)".strip()
RHEL = "Red Hat Enterprise Linux Server release 7.4 (Maipo)".strip()
TEST_HOSTNAME = "testhost.someplace.com"
Next for each test we need to build InputData
objects and populate it with the content
and build the expected return. Then finally we need to yield the pair.
16 input_data = InputData("test_fedora")
17 input_data.add(Specs.redhat_release, FEDORA)
18 input_data.add(Specs.hostname, TEST_HOSTNAME)
19 expected = make_pass("IS_FEDORA", hostname=TEST_HOSTNAME, product="Fedora")
20
21 yield input_data, expected
22
23 input_data = InputData("test_rhel")
24 input_data.add(Specs.redhat_release, RHEL)
25 input_data.add(Specs.hostname, TEST_HOSTNAME)
26 expected = make_fail("IS_FEDORA", hostname=TEST_HOSTNAME, product="Red Hat Enterprise Linux Server")
27
28 yield input_data, expected
Now for the entire test:
1from .. import is_fedora
2from insights.specs import Specs
3from insights.tests import InputData, archive_provider
4from insights.core.plugins import make_fail, make_pass
5
6FEDORA = "Fedora release 28 (Twenty Eight)"
7RHEL = "Red Hat Enterprise Linux Server release 7.4 (Maipo)"
8TEST_HOSTNAME = "testhost.someplace.com"
9
10
11@archive_provider(is_fedora.report)
12def integration_test():
13
14 input_data = InputData("test_fedora")
15 input_data.add(Specs.redhat_release, FEDORA)
16 input_data.add(Specs.hostname, TEST_HOSTNAME)
17 expected = make_pass("IS_FEDORA", hostname=TEST_HOSTNAME, product="Fedora")
18
19
20 yield input_data, expected
21
22 input_data = InputData("test_rhel")
23 input_data.add(Specs.redhat_release, RHEL)
24 input_data.add(Specs.hostname, TEST_HOSTNAME)
25 expected = make_fail("IS_FEDORA", hostname=TEST_HOSTNAME, product="Red Hat Enterprise Linux Server")
26
27 yield input_data, expected