Skip to content

Commit

Permalink
fix(globalConfig): update name and rest root convention (#1335)
Browse files Browse the repository at this point in the history
**Issue number:** ADDON-74883, #1333 
## Summary

### Changes

> Changed the validations for name and restRoot field according to the
conventions specified in ADDON-74883. Additionally, the add-on will not
be built if the name in `globalConfig` does not match the name in
`app.manifest`.

### User experience

> User has to keep the same add-on name in `globalConfig` and
`app.manifest`, if the name does not match then add-on will not be
built. This is usually never the case unless the `app.manifest or name
in globalConfig is changed manually after initializing the add-on.

## Checklist

If your change doesn't seem to apply, please leave them unchecked.

* [x] I have performed a self-review of this change
* [x] Changes have been tested
* [x] Changes are documented
* [x] PR title follows [conventional commit
semantics](https://www.conventionalcommits.org/en/v1.0.0/)

---------

Co-authored-by: srv-rr-github-token <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: sgoral-splunk <[email protected]>
Co-authored-by: Artem Rys <[email protected]>
  • Loading branch information
5 people authored Oct 1, 2024
1 parent 5cfc889 commit bdfa8c3
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .markdownlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ MD040: false
MD041: false

# MD046/code-block-style
MD046: false
MD046: false
6 changes: 6 additions & 0 deletions splunk_add_on_ucc_framework/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,12 @@ def generate(
f"Updated and saved add-on version in the globalConfig file to {addon_version}"
)
global_config.expand()
if ta_name != global_config.product:
logger.error(
"Add-on name mentioned in globalConfig meta tag and that app.manifest are not same,"
"please unify them to build the add-on."
)
sys.exit(1)
scheme = global_config_builder_schema.GlobalConfigBuilderSchema(global_config)
utils.recursive_overwrite(
os.path.join(internal_root_dir, "package"),
Expand Down
8 changes: 6 additions & 2 deletions splunk_add_on_ucc_framework/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@

logger = logging.getLogger("ucc_gen")

ADDON_NAME_RE_STR = r'^[^<>:"/|?*]+$'
ADDON_NAME_RE_STR = (
r"^(?!^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$)"
r"(?!.*\.(tar(\.gz)?|tgz|spl)$)"
r"[A-Za-z_.-][A-Za-z0-9_.-]*[A-Za-z0-9_-]$"
)
ADDON_NAME_RE = re.compile(ADDON_NAME_RE_STR)
ADDON_REST_ROOT_RE_STR = r"^\w+$"
ADDON_REST_ROOT_RE_STR = r"^[\w-]+$"
ADDON_REST_ROOT_RE = re.compile(ADDON_REST_ROOT_RE_STR)
ADDON_INPUT_NAME_RE_STR = r"^[0-9a-zA-Z][\w-]*$"
ADDON_INPUT_NAME_RE = re.compile(ADDON_INPUT_NAME_RE_STR)
Expand Down
4 changes: 2 additions & 2 deletions splunk_add_on_ucc_framework/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1848,12 +1848,12 @@
},
"name": {
"type": "string",
"pattern": "^[^<>:\"\\/\\\\|\\?\\*]+$",
"pattern": "^(?!^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$)(?!.*\\.(tar(\\.gz)?|tgz|spl)$)[A-Za-z_.-][A-Za-z0-9_.-]*[A-Za-z0-9_-]$",
"description": "Name used for API endpoints and all code references separating separating endpoints from any other app."
},
"restRoot": {
"type": "string",
"pattern": "^\\w+$",
"pattern": "^[\\w-]+$",
"description": "String used to create API endpoints."
},
"apiVersion": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ from splunklib import modularinput as smi

ADDON_NAME = "{{addon_name}}"


def logger_for_input(input_name: str) -> logging.Logger:
return log.Logs().get_logger(f"{ADDON_NAME.lower()}_{input_name}")

Expand All @@ -17,9 +16,9 @@ def get_account_api_key(session_key: str, account_name: str):
cfm = conf_manager.ConfManager(
session_key,
ADDON_NAME,
realm=f"__REST_CREDENTIAL__#{ADDON_NAME}#configs/conf-{{addon_rest_root}}_account",
realm=f"__REST_CREDENTIAL__#{ADDON_NAME}#configs/conf-{{addon_rest_root| lower}}_account",
)
account_conf_file = cfm.get_conf("{{addon_name}}_account")
account_conf_file = cfm.get_conf("{{addon_rest_root | lower}}_account")
return account_conf_file.get(account_name).get("api_key")


Expand Down Expand Up @@ -61,7 +60,7 @@ def stream_events(inputs: smi.InputDefinition, event_writer: smi.EventWriter):
logger=logger,
session_key=session_key,
app_name=ADDON_NAME,
conf_name=f"{ADDON_NAME}_settings",
conf_name="{{addon_rest_root | lower}}_settings",
)
logger.setLevel(log_level)
log.modular_input_start(logger, normalized_input_name)
Expand Down
1 change: 1 addition & 0 deletions tests/smoke/test_ucc_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def test_ucc_init():
"Demo Add-on for Splunk",
"demo_input",
"1.0.0",
"demo-addon-for-splunk",
overwrite=True,
)
expected_folder = os.path.join(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
},
"meta": {
"name": "demo_addon_for_splunk",
"restRoot": "demo_addon_for_splunk",
"restRoot": "demo-addon-for-splunk",
"version": "1.0.0",
"displayName": "Demo Add-on for Splunk",
"schemaVersion": "0.0.8",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

ADDON_NAME = "demo_addon_for_splunk"


def logger_for_input(input_name: str) -> logging.Logger:
return log.Logs().get_logger(f"{ADDON_NAME.lower()}_{input_name}")

Expand All @@ -17,9 +16,9 @@ def get_account_api_key(session_key: str, account_name: str):
cfm = conf_manager.ConfManager(
session_key,
ADDON_NAME,
realm=f"__REST_CREDENTIAL__#{ADDON_NAME}#configs/conf-demo_addon_for_splunk_account",
realm=f"__REST_CREDENTIAL__#{ADDON_NAME}#configs/conf-demo-addon-for-splunk_account",
)
account_conf_file = cfm.get_conf("demo_addon_for_splunk_account")
account_conf_file = cfm.get_conf("demo-addon-for-splunk_account")
return account_conf_file.get(account_name).get("api_key")


Expand Down Expand Up @@ -61,7 +60,7 @@ def stream_events(inputs: smi.InputDefinition, event_writer: smi.EventWriter):
logger=logger,
session_key=session_key,
app_name=ADDON_NAME,
conf_name=f"{ADDON_NAME}_settings",
conf_name="demo-addon-for-splunk_settings",
)
logger.setLevel(log_level)
log.modular_input_start(logger, normalized_input_name)
Expand Down
47 changes: 46 additions & 1 deletion tests/unit/commands/test_build.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import os
from unittest.mock import MagicMock, patch

import pytest

from splunk_add_on_ucc_framework.commands.build import (
_add_modular_input,
_get_build_output_path,
_get_python_version_from_executable,
_get_and_check_global_config_path,
generate,
)
from splunk_add_on_ucc_framework.exceptions import (
CouldNotIdentifyPythonVersionException,
Expand Down Expand Up @@ -147,3 +147,48 @@ def test_add_modular_input(GlobalConfig, tmp_path):
helper_path = tmp_path / ta_name / "bin" / "example_helper.py"
assert input_path.is_file()
assert helper_path.is_file()


@patch("splunk_add_on_ucc_framework.global_config.GlobalConfig")
@patch("splunk_add_on_ucc_framework.commands.build._get_app_manifest")
@patch("splunk_add_on_ucc_framework.commands.build._get_and_check_global_config_path")
@patch("os.path.exists")
@patch(
"splunk_add_on_ucc_framework.commands.build.global_config_update.handle_global_config_update"
)
@patch(
"splunk_add_on_ucc_framework.commands.build.global_config_validator.GlobalConfigValidator.validate"
)
def test_ta_name_mismatch(
mock_GlobalConfigValidator,
mock_global_config_update,
mock_os_path,
mock_get_and_check_global_config_path,
mock_get_app_manifest,
mock_global_config,
caplog,
):
mock_os_path.return_value = True

mock_app_manifest = MagicMock()
mock_app_manifest.get_addon_name.return_value = "ta_name_1"
mock_get_app_manifest.return_value = mock_app_manifest

mock_global_config_instance = MagicMock()
mock_global_config_instance.product = "ta_name_2"
mock_get_and_check_global_config_path.return_value = "mock_gc_path"
mock_global_config.return_value = mock_global_config_instance

mock_global_config_update.return_value = None
mock_GlobalConfigValidator.return_value = True

with pytest.raises(SystemExit):
generate(
source="source/path",
addon_version="1.0.0",
python_binary_name="python3",
verbose_file_summary_report=False,
pip_version="latest",
pip_legacy_resolver=False,
ui_source_map=False,
)
60 changes: 55 additions & 5 deletions tests/unit/commands/test_init.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from unittest import mock

import tests.unit.helpers as helpers
import json
import pytest

from splunk_add_on_ucc_framework.commands import init
Expand All @@ -11,6 +12,37 @@
("test-addon", True),
("demo_addon", True),
("foo/bar/baz", False),
("Test.", False),
("12Test", False),
("test-addon-123", True),
("test.tar", False),
("test.tgz", False),
("test.tar.gz", False),
("test.spl", False),
("CON", False),
("PRN", False),
("AUX", False),
("NUL", False),
("COM1", False),
("COM2", False),
("COM3", False),
("COM4", False),
("COM5", False),
("COM6", False),
("COM7", False),
("COM8", False),
("COM9", False),
("LPT1", False),
("LPT2", False),
("LPT3", False),
("LPT4", False),
("LPT5", False),
("LPT6", False),
("LPT7", False),
("LPT8", False),
("LPT9", False),
("test@add-on", False),
("test.add-on_123_", True),
],
)
def test__is_valid_addon_name(addon_name, expected):
Expand All @@ -20,8 +52,11 @@ def test__is_valid_addon_name(addon_name, expected):
@pytest.mark.parametrize(
"rest_root,expected",
[
("test-addon", False),
("test-addon", True),
("demo_addon", True),
("test@addon", False),
("Test!_addon", False),
("test-addon_123", True),
],
)
def test__is_valid_rest_root(rest_root, expected):
Expand Down Expand Up @@ -115,7 +150,7 @@ def test_init(mock_generate_addon, init_kwargs, expected_args_to_generate_addon)
),
(
{
"addon_name": "addon-name",
"addon_name": "addon-name()",
"addon_display_name": "Addon For Demo",
"addon_input_name": "input_name",
"addon_version": "0.0.1",
Expand All @@ -124,7 +159,7 @@ def test_init(mock_generate_addon, init_kwargs, expected_args_to_generate_addon)
(
{
"addon_name": "addon_name",
"addon_rest_root": "addon-name",
"addon_rest_root": "addon!name",
"addon_display_name": "Addon For Demo",
"addon_input_name": "input_name",
"addon_version": "0.0.1",
Expand All @@ -135,7 +170,7 @@ def test_init(mock_generate_addon, init_kwargs, expected_args_to_generate_addon)
"addon_name": "addon_name",
"addon_rest_root": "addon_rest_root",
"addon_display_name": "Addon For Demo",
"addon_input_name": "foo" * 51,
"addon_input_name": "x" * 51,
"addon_version": "0.0.1",
}
),
Expand All @@ -162,3 +197,18 @@ def test_init_when_folder_already_exists(mock_generate_addon, caplog):
"option to overwrite the content of existing folder."
)
assert expected_error_message in caplog.text


def test_valid_regex():
file_path = f"{helpers.get_path_to_source_dir()}/schema/schema.json"
with open(file_path) as file:
content = file.read()
schema_json_content = json.loads(content)
restRoot_regex = schema_json_content["definitions"]["Meta"]["properties"][
"restRoot"
]["pattern"]
name_regex = schema_json_content["definitions"]["Meta"]["properties"]["name"][
"pattern"
]
assert init.ADDON_REST_ROOT_RE_STR == restRoot_regex
assert init.ADDON_NAME_RE_STR == name_regex

0 comments on commit bdfa8c3

Please sign in to comment.