Skip to content

Commit

Permalink
feat: implement banner output (ansible#625)
Browse files Browse the repository at this point in the history
Adds banner-type output to ansible-rulebook in the manner previously
demonstrated.

There's an open question as to how we want to handle outputting events
in rule_set_runner.py.
The previous code disabled args.print_events if verbosity was 2+ as the
logging would output the event.
We shouldn't have two different forms of output for the same data and
I'd opt for only the args.print_event form in all cases for consistency
unless there's specific, great enough value in using the logger when
verbosity is 2+.
At present, this code forcibly enables args.print_events when verbosity
is 2+ so both forms are output.

---------

Signed-off-by: Joe Shimkus <[email protected]>
  • Loading branch information
jshimkus-rh authored Jan 3, 2024
1 parent e17f1cb commit c72a420
Show file tree
Hide file tree
Showing 13 changed files with 400 additions and 68 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
- Support for standalone boolean in conditions
- Add basic auth to controller

### Changed
- Generic print as well as printing of events use new banner style

### Fixed

## [1.0.4] - 2023-10-30
Expand Down
26 changes: 12 additions & 14 deletions ansible_rulebook/action/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
import logging
import sys
from dataclasses import asdict
from pprint import pprint

import dpath
from drools import ruleset as lang

from ansible_rulebook.util import get_horizontal_rule
from ansible_rulebook import terminal

from .control import Control
from .helper import Helper
Expand All @@ -41,28 +40,26 @@ class Debug:
def __init__(self, metadata: Metadata, control: Control, **action_args):
self.helper = Helper(metadata, control, "debug")
self.action_args = action_args
self.display = terminal.Display()

async def __call__(self):
if "msg" in self.action_args:
messages = self.action_args.get("msg")
if not isinstance(messages, list):
messages = [messages]
for msg in messages:
print(msg)
self.display.banner("debug", msg)
elif "var" in self.action_args:
key = self.action_args.get("var")
try:
print(
dpath.get(
self.helper.control.variables, key, separator="."
)
value = dpath.get(
self.helper.control.variables, key, separator="."
)
self.display.banner("debug", f"{key}: {value}")
except KeyError:
logger.error("Key %s not found in variable pool", key)
raise
else:
print(get_horizontal_rule("="))
print("kwargs:")
args = asdict(self.helper.metadata)
project_data_file = self.helper.control.project_data_file
args.update(
Expand All @@ -73,11 +70,12 @@ async def __call__(self):
"project_data_file": project_data_file,
}
)
pprint(args)
print(get_horizontal_rule("="))
print("facts:")
pprint(lang.get_facts(self.helper.metadata.rule_set))
print(get_horizontal_rule("="))
self.display.banner("debug: kwargs", args, pretty=True)
self.display.banner(
"debug: facts",
lang.get_facts(self.helper.metadata.rule_set),
pretty=True,
)

sys.stdout.flush()
await self.helper.send_default_status()
15 changes: 8 additions & 7 deletions ansible_rulebook/action/print_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# limitations under the License.

import sys
from pprint import pprint
from typing import Callable

from ansible_rulebook import terminal

from .control import Control
from .helper import Helper
Expand All @@ -30,16 +30,17 @@ class PrintEvent:
def __init__(self, metadata: Metadata, control: Control, **action_args):
self.helper = Helper(metadata, control, "print_event")
self.action_args = action_args
self.display = terminal.Display()

async def __call__(self):
print_fn: Callable = print
if self.action_args.get("pretty", False):
print_fn = pprint

var_name = (
"events" if "events" in self.helper.control.variables else "event"
)

print_fn(self.helper.control.variables[var_name])
self.display.banner(
"event",
self.helper.control.variables[var_name],
pretty=self.action_args.get("pretty", False),
)
sys.stdout.flush()
await self.helper.send_default_status()
17 changes: 7 additions & 10 deletions ansible_rulebook/action/shutdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from ansible_rulebook.exception import ShutdownException
from ansible_rulebook.messages import Shutdown as ShutdownMessage
from ansible_rulebook.terminal import Display
from ansible_rulebook.util import run_at

from .control import Control
Expand Down Expand Up @@ -43,16 +44,12 @@ async def __call__(self):
"kind": kind,
}
)
print(
"Ruleset: %s rule: %s has initiated shutdown of type: %s. "
"Delay: %.3f seconds, Message: %s"
% (
self.helper.metadata.rule_set,
self.helper.metadata.rule,
kind,
delay,
message,
)
Display.instance().banner(
"ruleset",
f"{self.helper.metadata.rule_set}"
f" rule: {self.helper.metadata.rule}"
f" has initiated shutdown of type: {kind}."
f" Delay: {delay:.3f} seconds, Message: {message}",
)
raise ShutdownException(
ShutdownMessage(message=message, delay=delay, kind=kind)
Expand Down
12 changes: 9 additions & 3 deletions ansible_rulebook/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@

import ansible_rulebook # noqa: E402
from ansible_rulebook import app # noqa: E402
from ansible_rulebook import terminal # noqa: E402
from ansible_rulebook.conf import settings # noqa: E402
from ansible_rulebook.job_template_runner import ( # noqa: E402
job_template_runner,
)

display = terminal.Display()

DEFAULT_VERBOSITY = 0

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -227,11 +230,15 @@ def setup_logging(args: argparse.Namespace) -> None:
if args.verbosity >= 2:
level = logging.DEBUG
stream = sys.stdout
args.print_events = False
elif args.verbosity == 1:
level = logging.INFO
stream = sys.stdout

# As Display is a singleton if it was created elsewhere we may need to
# adjust the level.
if display.level > level:
display.level = level

logging.basicConfig(stream=stream, level=level, format=LOG_FORMAT)
logging.getLogger("drools.").setLevel(level)

Expand All @@ -244,6 +251,7 @@ def main(args: List[str] = None) -> int:

args = parser.parse_args(args)
validate_args(args)
setup_logging(args)

if args.controller_url:
job_template_runner.host = args.controller_url
Expand Down Expand Up @@ -271,8 +279,6 @@ def main(args: List[str] = None) -> int:
if args.execution_strategy:
settings.default_execution_strategy = args.execution_strategy

setup_logging(args)

try:
asyncio.run(app.run(args))
except KeyboardInterrupt:
Expand Down
6 changes: 5 additions & 1 deletion ansible_rulebook/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import yaml

from ansible_rulebook import terminal

ANSIBLE_GALAXY = shutil.which("ansible-galaxy")
EDA_PATH_PREFIX = "extensions/eda"

Expand Down Expand Up @@ -130,7 +132,9 @@ def load_rulebook(collection, rulebook):
if not location:
return False
with open(location) as f:
print(f"Loading rulebook from {location}")
terminal.Display.instance().banner(
"collection", f"Loading rulebook from {location}"
)
return yaml.safe_load(f.read())


Expand Down
20 changes: 15 additions & 5 deletions ansible_rulebook/rule_set_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import gc
import logging
import uuid
from pprint import PrettyPrinter, pformat
from pprint import pformat
from types import MappingProxyType
from typing import Dict, List, Optional, Union, cast

Expand All @@ -28,6 +28,7 @@
)
from drools.ruleset import session_stats

from ansible_rulebook import terminal
from ansible_rulebook.action.control import Control
from ansible_rulebook.action.debug import Debug
from ansible_rulebook.action.metadata import Metadata
Expand Down Expand Up @@ -102,6 +103,7 @@ def __init__(
self.active_actions = set()
self.broadcast_method = broadcast_method
self.event_counter = 0
self.display = terminal.Display()

async def run_ruleset(self):
tasks = []
Expand Down Expand Up @@ -203,12 +205,20 @@ async def _drain_source_queue(self):
try:
while True:
data = await self.ruleset_queue_plan.source_queue.get()
# Default to output events at debug level.
level = logging.DEBUG

# If print_events is specified adjust the level to the
# display's current level to guarantee output.
if self.parsed_args and self.parsed_args.print_events:
PrettyPrinter(indent=4).pprint(data)
level = self.display.level

self.display.banner("received event", level=level)
self.display.output(f"Ruleset: {self.name}", level=level)
self.display.output("Event:", level=level)
self.display.output(data, pretty=True, level=level)
self.display.banner(level=level)

logger.debug(
"Ruleset: %s, received event: %s ", self.name, str(data)
)
if isinstance(data, Shutdown):
self.shutdown = data
return await self._handle_shutdown()
Expand Down
Loading

0 comments on commit c72a420

Please sign in to comment.