Skip to content

Commit b8a293a

Browse files
committed
add var substitution support
Signed-off-by: Sylvain Hellegouarch <[email protected]>
1 parent 264f157 commit b8a293a

File tree

4 files changed

+78
-9
lines changed

4 files changed

+78
-9
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
[Unreleased]: https://github.com/chaostoolkit/chaostoolkit-reporting/compare/0.14.3...HEAD
66

7+
### Added
8+
9+
- Support to substitute values in arguments so we know how activities were
10+
called. You can now pass `--var` and `--var-file` to generate the report
11+
as you do when you run the experiment
12+
713
## [0.14.3][] - 2023-06-09
814

915
[0.14.3]: https://github.com/chaostoolkit/chaostoolkit-reporting/compare/0.14.2...0.14.3

chaosreport/__init__.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import tempfile
1111
from base64 import b64encode
1212
from datetime import datetime, timedelta
13-
from typing import List
13+
from typing import Any, Dict, List
1414

1515
import cairosvg
1616
import dateparser
@@ -20,8 +20,11 @@
2020
import pygal
2121
import pypandoc
2222
import semver
23+
from chaoslib import merge_vars, substitute
2324
from chaoslib.caching import cache_activities, lookup_activity
24-
from chaoslib.types import Experiment, Journal, Run
25+
from chaoslib.configuration import load_configuration
26+
from chaoslib.secret import load_secrets
27+
from chaoslib.types import Configuration, Experiment, Journal, Run, Secrets
2528
from jinja2 import Environment, PackageLoader
2629
from logzero import logger
2730
from natural import date
@@ -244,7 +247,12 @@ def generate_report_header(
244247
return header
245248

246249

247-
def generate_report(journal_path: str, export_format: str = "markdown") -> str:
250+
def generate_report(
251+
journal_path: str,
252+
export_format: str = "markdown",
253+
var: Dict[str, Any] = None,
254+
var_file: List[str] = None,
255+
) -> str:
248256
"""
249257
Generate a report document from a chaostoolkit journal.
250258
@@ -267,7 +275,14 @@ def generate_report(journal_path: str, export_format: str = "markdown") -> str:
267275

268276
generate_chart_from_metric_probes(journal, export_format)
269277
add_contribution_model(journal, export_format)
270-
template = get_report_template(journal["chaoslib-version"])
278+
config_vars, secret_vars = merge_vars(var, var_file) or (None, None)
279+
config = load_configuration(
280+
experiment.get("configuration", {}), config_vars
281+
)
282+
secrets = load_secrets(experiment.get("secrets", {}), secret_vars)
283+
template = get_report_template(
284+
journal["chaoslib-version"], configuration=config, secrets=secrets
285+
)
271286
report = template.render(journal)
272287

273288
return report
@@ -333,7 +348,10 @@ def save_report(
333348

334349

335350
def get_report_template(
336-
report_version: str, default_template: str = "index.md"
351+
report_version: str,
352+
default_template: str = "index.md",
353+
configuration: Configuration = None,
354+
secrets: Secrets = None,
337355
):
338356
"""
339357
Retrieve and return the most appropriate template based on the
@@ -346,6 +364,13 @@ def get_report_template(
346364
env.globals["pretty_duration"] = lambda d0, d1: date.delta(
347365
dateparser.parse(d0), dateparser.parse(d1), words=False
348366
)[0]
367+
env.globals["substitute"] = (
368+
lambda args: {
369+
k: substitute(v, configuration, secrets) for k, v in args.items()
370+
}
371+
if isinstance(args, dict)
372+
else args
373+
)
349374

350375
if not report_version:
351376
return env.get_template(default_template)

chaosreport/cli.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,62 @@
11
# -*- coding: utf-8 -*-
22
import os
33
from glob import glob
4+
from typing import Any, Dict, List
45

56
import click
7+
from chaoslib import convert_vars
68

79
from chaosreport import generate_report, generate_report_header, save_report
810

911
__all__ = ["report"]
1012

1113

14+
def validate_vars(
15+
ctx: click.Context, param: click.Option, value: List[str]
16+
) -> Dict[str, Any]:
17+
"""
18+
Process all `--var key=value` and return a dictionary of them with the
19+
value converted to the appropriate type.
20+
"""
21+
try:
22+
return convert_vars(value)
23+
except ValueError as x:
24+
raise click.BadParameter(str(x))
25+
26+
1227
@click.command()
1328
@click.option(
1429
"--export-format",
1530
default="markdown",
1631
help="Format to export the report to: html, markdown, pdf.",
1732
)
33+
@click.option(
34+
"--var",
35+
multiple=True,
36+
callback=validate_vars,
37+
help="Specify substitution values for configuration only. Can "
38+
"be provided multiple times. The pattern must be "
39+
"key=value or key:type=value. In that latter case, the "
40+
"value will be casted as the specified type. Supported "
41+
"types are: int, float, bytes. No type specified means "
42+
"a utf-8 decoded string.",
43+
)
44+
@click.option(
45+
"--var-file",
46+
multiple=True,
47+
type=click.Path(exists=True),
48+
help="Specify files that contain configuration and secret "
49+
"substitution values. Either as a json/yaml payload where "
50+
"each key has a value mapping to a configuration entry. "
51+
"Or a .env file defining environment variables. "
52+
"Can be provided multiple times.",
53+
)
1854
@click.argument("journal", type=click.Path(exists=True), nargs=-1)
1955
@click.argument("report", type=click.Path(exists=False), nargs=1)
2056
def report(
2157
export_format: str = "markdown",
58+
var: Dict[str, Any] = None,
59+
var_file: List[str] = None,
2260
journal: str = "journal.json",
2361
report: str = "report.md",
2462
):
@@ -33,6 +71,6 @@ def report(
3371
journal = glob(journal)
3472

3573
for journal in journal:
36-
reports.append(generate_report(journal, export_format))
74+
reports.append(generate_report(journal, export_format, var, var_file))
3775
save_report(header, reports, report_path, export_format)
3876
click.echo("Report generated as '{f}'".format(f=report))

chaosreport/template/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,22 @@ The {{item.activity.type}} provider that was executed:
117117
| **Type** | {{item.activity.provider.type}} |
118118
| **Path** | {{item.activity.provider.path}} |
119119
| **Timeout** | {{item.activity.provider.get("timeout", "N/A")}} |
120-
| **Arguments** | {{item.activity.provider.get("arguments", "N/A")}} |
120+
| **Arguments** | {{substitute(item.activity.provider.get("arguments", "N/A"))}} |
121121
{% elif item.activity.provider.type == "http" %}
122122
| | |
123123
| --------------- | ---------------------------------------------------------- |
124124
| **Type** | {{item.activity.provider.type}} |
125125
| **URL** | {{item.activity.provider.url}} |
126126
| **Method** | {{item.activity.provider.get("method", "GET")}} |
127127
| **Timeout** | {{item.activity.provider.get("timeout", "N/A")}} |
128-
| **Arguments** | {{item.activity.provider.get("arguments", "N/A")}} |
128+
| **Arguments** | {{substitute(item.activity.provider.get("arguments", "N/A"))}} |
129129
{% else %}
130130
| | |
131131
| --------------- | ---------------------------------------------------------- |
132132
| **Type** | {{item.activity.provider.type}} |
133133
| **Module** | {{item.activity.provider.module}} |
134134
| **Function** | {{item.activity.provider.func}} |
135-
| **Arguments** | {{item.activity.provider.get("arguments", "N/A")}} |
135+
| **Arguments** | {{substitute(item.activity.provider.get("arguments", "N/A"))}} |
136136
{% endif %}
137137

138138
{% if item.exception %}

0 commit comments

Comments
 (0)