Skip to content

Commit

Permalink
Merge branch 'main' into AAP-15000_trim_docker_image
Browse files Browse the repository at this point in the history
  • Loading branch information
ttuffin authored Oct 4, 2023
2 parents 4fba55b + 1a2212e commit e7f650b
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 28 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,25 @@ env:
QUAY_USER: ansible+eda_gha

jobs:
build-and-test-image:
if: github.repository == 'ansible/ansible-rulebook'
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Build local image
run: docker build -t localhost/ansible-rulebook:test .

- name: Run tests
run: >
docker run --rm -u 0 localhost/ansible-rulebook:test bash -c '
pip install -r requirements_test.txt &&
pytest -m "e2e" -n auto'
build-and-push-image:
if: github.repository == 'ansible/ansible-rulebook'
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ repos:
additional_dependencies:
- flake8-bugbear
- repo: local
language: javascript
hooks:
- id: ajv
name: ajv
Expand Down
1 change: 1 addition & 0 deletions ansible_rulebook/schema/ruleset_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
}
},
"required": [
"name",
"hosts",
"sources",
"rules"
Expand Down
21 changes: 21 additions & 0 deletions docs/actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ Run an Ansible playbook.
* - json_mode
- Boolean, sends the playbook events data to the stdout as json strings as they are processed by ansible-runner
- No
* - copy_files
- Boolean, copy the local playbook file to the ansible-runner project directory, this is not needed if you are running a playbook from an ansible collection.
- No


run_module
Expand Down Expand Up @@ -96,6 +99,21 @@ Run an Ansible module
* - extra_vars
- Additional vars to be passed into the playbook as extra vars.
- No
* - json_mode
- Boolean, sends the playbook events data to the stdout as json strings as they are processed by ansible-runner
- No
* - set_facts
- Boolean, the artifacts from the module execution are inserted back into the rule set as facts
- No
* - post_events
- Boolean, the artifacts from the module execution are inserted back into the rule set as events
- No
* - ruleset
- The name of the ruleset to post the event or assert the fact to, default is current rule set.
- No
* - var_root
- If the event is a deeply nested dictionary, the var_root can specify the key name whose value should replace the matching event value. The var_root can take a dictionary to account for data when we have multiple matching events.
- No

run_job_template
****************
Expand Down Expand Up @@ -312,6 +330,9 @@ retract_fact
* - ruleset
- The name of the rule set to retract the fact, default is the current rule set name
- No
* - partial
- The fact being requested to retracted is partial and doesn't have all the keys. Default is true
- No

Example:

Expand Down
27 changes: 27 additions & 0 deletions docs/conditions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -966,3 +966,30 @@ Example:
| if an attribute exists before you use it in a condition. The rule engine
| will check for the existence and only then compare it. If its missing, the
| comparison fails.

| **Q:** If a condition string has an embedded colon followed by a space in it how do I escape it?
| **Ans:** During the rulebook parsing you would see this error message:
| ERROR - Terminating mapping values are not allowed here.
| To resove this eror you would have to quote the whole condition string or use the > or | and
| move the entire condition to a separate line.
Example:
.. code-block:: yaml
name: rule1
condition: 'event.abc == "test: 1"'
.. code-block:: yaml
name: rule1
condition: >
event.abc == "test: 1"
.. code-block:: yaml
name: rule1
condition: |
event.abc == "test: 1"
26 changes: 0 additions & 26 deletions tests/e2e/files/rulebooks/82_non_alpha_keys.yml

This file was deleted.

2 changes: 1 addition & 1 deletion tests/e2e/test_non_alpha_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async def test_non_alpha_numeric_keys():
endpoint = "/api/ws2"
proc_id = "42"
port = 31415
rulebook = utils.BASE_DATA_PATH / "rulebooks/82_non_alpha_keys.yml"
rulebook = utils.EXAMPLES_PATH / "82_non_alpha_keys.yml"
websocket_address = f"ws://localhost:{port}{endpoint}"
cmd = utils.Command(
rulebook=rulebook,
Expand Down
108 changes: 108 additions & 0 deletions tests/e2e/test_run_module_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
Module with tests for websockets
"""
import asyncio
import logging
from functools import partial

import dpath
import pytest
import websockets.server as ws_server

from . import utils

LOGGER = logging.getLogger(__name__)
DEFAULT_TIMEOUT = 15


@pytest.mark.e2e
@pytest.mark.asyncio
async def test_run_module_output():
"""
Verify that ansible-rulebook can handle output of
run_module and then used in a condition
"""
# variables
host = "localhost"
endpoint = "/api/ws2"
proc_id = "42"
port = 31415
rulebook = utils.EXAMPLES_PATH / "29_run_module.yml"
websocket_address = f"ws://localhost:{port}{endpoint}"
cmd = utils.Command(
rulebook=rulebook,
websocket=websocket_address,
proc_id=proc_id,
heartbeat=2,
)

# run server and ansible-rulebook
queue = asyncio.Queue()
handler = partial(utils.msg_handler, queue=queue)
async with ws_server.serve(handler, host, port):
LOGGER.info(f"Running command: {cmd}")
proc = await asyncio.create_subprocess_shell(
str(cmd),
cwd=utils.BASE_DATA_PATH,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)

await asyncio.wait_for(proc.wait(), timeout=DEFAULT_TIMEOUT)
assert proc.returncode == 0

# Verify data
assert not queue.empty()

action_counter = 0
session_stats_counter = 0
stats = None
rule_matches = {
"r1": {
"action": "run_module",
"event_key": "m/i",
"event_value": 1,
},
"r2": {
"action": "print_event",
"event_key": "m/message",
"event_value": "FRED FLINTSTONE",
},
}
while not queue.empty():
data = await queue.get()
assert data["path"] == endpoint
data = data["payload"]

if data["type"] == "Action":
action_counter += 1
assert data["action_uuid"] is not None
assert data["ruleset_uuid"] is not None
assert data["rule_uuid"] is not None
assert data["status"] == "successful"
rule_name = data["rule"]
assert rule_name in rule_matches.keys()

matching_events = data["matching_events"]
assert (
dpath.get(
matching_events, rule_matches[rule_name]["event_key"]
)
== rule_matches[rule_name]["event_value"]
)
assert data["action"] == rule_matches[rule_name]["action"]

if data["type"] == "SessionStats":
session_stats_counter += 1
stats = data["stats"]
assert stats["ruleSetName"] == "29 run module"
assert stats["numberOfRules"] == 2
assert stats["numberOfDisabledRules"] == 0
assert data["activation_id"] == proc_id

assert stats["rulesTriggered"] == 2
assert stats["eventsProcessed"] == 6
assert stats["eventsMatched"] == 2

assert session_stats_counter >= 2
assert action_counter == 2
1 change: 1 addition & 0 deletions tests/e2e/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

BASE_DATA_PATH = Path(f"{__file__}").parent / Path("files")
DEFAULT_SOURCES = Path(f"{__file__}").parent / Path("../sources")
EXAMPLES_PATH = Path(f"{__file__}").parent / Path("../examples")
DEFAULT_INVENTORY = BASE_DATA_PATH / "inventories/default_inventory.yml"


Expand Down

0 comments on commit e7f650b

Please sign in to comment.