-
Notifications
You must be signed in to change notification settings - Fork 520
/
Copy pathcustom_rules.py
150 lines (122 loc) · 5.6 KB
/
custom_rules.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
"""Commands for supporting custom rules."""
from pathlib import Path
import click
import yaml
from .main import root
from .utils import get_etc_path, load_etc_dump, ROOT_DIR
from semver import Version
DEFAULT_CONFIG_PATH = Path(get_etc_path('_config.yaml'))
CUSTOM_RULES_DOC_PATH = Path(ROOT_DIR).joinpath('docs', 'custom-rules.md')
@root.group('custom-rules')
def custom_rules():
"""Commands for supporting custom rules."""
def create_config_content() -> str:
"""Create the initial content for the _config.yaml file."""
# Base structure of the configuration
config_content = {
'rule_dirs': ['rules'],
'bbr_rules_dirs': ['rules_building_block'],
'directories': {
'action_dir': 'actions',
'action_connector_dir': 'action_connectors',
'exception_dir': 'exceptions',
},
'files': {
'deprecated_rules': 'etc/deprecated_rules.json',
'packages': 'etc/packages.yaml',
'stack_schema_map': 'etc/stack-schema-map.yaml',
'version_lock': 'etc/version.lock.json',
},
'testing': {
'config': 'etc/test_config.yaml'
}
}
return yaml.safe_dump(config_content, default_flow_style=False)
def create_test_config_content(enable_prebuilt_tests: bool) -> str:
"""Generate the content for the test_config.yaml with special content and references."""
def format_test_string(test_string: str, comment_char: str) -> str:
"""Generate a yaml formatted string with a comment character."""
return f"{comment_char} - {test_string}"
comment_char = "#" if enable_prebuilt_tests else ""
example_test_config_path = DEFAULT_CONFIG_PATH.parent.joinpath("example_test_config.yaml")
lines = [
"# For more details, refer to the example configuration:",
f"# {example_test_config_path}",
"# Define tests to explicitly bypass, with all others being run.",
"# To run all tests, set bypass to empty or leave this file commented out.",
"",
"unit_tests:",
" bypass:",
format_test_string("tests.test_gh_workflows.TestWorkflows.test_matrix_to_lock_version_defaults", comment_char),
format_test_string(
"tests.test_schemas.TestVersionLockSchema.test_version_lock_has_nested_previous", comment_char
),
format_test_string("tests.test_packages.TestRegistryPackage.test_registry_package_config", comment_char),
format_test_string("tests.test_all_rules.TestValidRules.test_schema_and_dupes", comment_char),
]
return "\n".join(lines)
@custom_rules.command('setup-config')
@click.argument('directory', type=Path)
@click.argument('kibana-version', type=str, default=load_etc_dump('packages.yaml')['package']['name'])
@click.option('--overwrite', is_flag=True, help="Overwrite the existing _config.yaml file.")
@click.option(
"--enable-prebuilt-tests", "-e", is_flag=True, help="Enable all prebuilt tests instead of default subset."
)
def setup_config(directory: Path, kibana_version: str, overwrite: bool, enable_prebuilt_tests: bool):
"""Setup the custom rules configuration directory and files with defaults."""
config = directory / '_config.yaml'
if not overwrite and config.exists():
raise FileExistsError(f'{config} already exists. Use --overwrite to update')
etc_dir = directory / 'etc'
test_config = etc_dir / 'test_config.yaml'
package_config = etc_dir / 'packages.yaml'
stack_schema_map_config = etc_dir / 'stack-schema-map.yaml'
config_files = [
package_config,
stack_schema_map_config,
test_config,
config,
]
directories = [
directory / 'actions',
directory / 'action_connectors',
directory / 'exceptions',
directory / 'rules',
directory / 'rules_building_block',
etc_dir,
]
version_files = [
etc_dir / 'deprecated_rules.json',
etc_dir / 'version.lock.json',
]
# Create directories
for dir_ in directories:
dir_.mkdir(parents=True, exist_ok=True)
click.echo(f'Created directory: {dir_}')
# Create version_files and populate with default content if applicable
for file_ in version_files:
file_.write_text('{}')
click.echo(
f'Created file with default content: {file_}'
)
# Create the stack-schema-map.yaml file
stack_schema_map_content = load_etc_dump('stack-schema-map.yaml')
latest_version = max(stack_schema_map_content.keys(), key=lambda v: Version.parse(v))
latest_entry = {latest_version: stack_schema_map_content[latest_version]}
stack_schema_map_config.write_text(yaml.safe_dump(latest_entry, default_flow_style=False))
# Create default packages.yaml
package_content = {'package': {'name': kibana_version}}
package_config.write_text(yaml.safe_dump(package_content, default_flow_style=False))
# Create and configure test_config.yaml
test_config.write_text(create_test_config_content(enable_prebuilt_tests))
# Create and configure _config.yaml
config.write_text(create_config_content())
for file_ in config_files:
click.echo(f'Created file with default content: {file_}')
click.echo(f'\n# For details on how to configure the _config.yaml file,\n'
f'# consult: {DEFAULT_CONFIG_PATH.resolve()}\n'
f'# or the docs: {CUSTOM_RULES_DOC_PATH.resolve()}')