Skip to content

Commit adcdf7a

Browse files
chore: merge develop into main (#2010)
2 parents 9ef1d32 + 0531328 commit adcdf7a

96 files changed

Lines changed: 5269 additions & 5897 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-test-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ jobs:
296296
with:
297297
name: test-ui-splunkd-splunkd-${{ matrix.splunk.version }}-${{ matrix.test-group }}.log
298298
path: ./splunkd.log
299-
- uses: dorny/test-reporter@v2
299+
- uses: dorny/test-reporter@v3
300300
if: success() || failure()
301301
with:
302302
name: test-report-ui-${{ matrix.splunk.version }}-${{ matrix.test-group }}

poetry.lock

Lines changed: 731 additions & 639 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ validate = ["splunk-appinspect"]
6868
mkdocs = "^1.6.1"
6969
pytest = "^7.2.1"
7070
pytest-splunk-addon = "^6.0.0"
71-
pytest-splunk-addon-ui-smartx = "6.0.0"
71+
pytest-splunk-addon-ui-smartx = "6.0.1"
7272
pytest-rerunfailures = "^11.1.1"
7373
mkdocs-material = "^9.6.16"
7474
mkdocstrings = {version=">=0", extras=["python"]}

splunk_add_on_ucc_framework/commands/build.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,27 @@
6969
internal_root_dir = os.path.dirname(os.path.dirname(__file__))
7070

7171

72+
def _inject_app_name_in_base_html(ta_name: str, outputdir: str) -> None:
73+
"""
74+
Replace __APP_NAME__ placeholder in base.html with the actual add-on name.
75+
76+
Args:
77+
ta_name: Add-on name.
78+
outputdir: output directory.
79+
"""
80+
base_html_path = os.path.join(
81+
outputdir, ta_name, "appserver", "templates", "base.html"
82+
)
83+
if not os.path.isfile(base_html_path):
84+
return
85+
with open(base_html_path) as f:
86+
content = f.read()
87+
with open(base_html_path, "w") as f:
88+
# Splunk static app URLs are keyed by the real app name from the package.
89+
# Lowercasing here breaks asset resolution for mixed-case app names.
90+
f.write(content.replace("__APP_NAME__", ta_name))
91+
92+
7293
def _modify_and_replace_token_for_oauth_templates(
7394
ta_name: str, global_config: global_config_lib.GlobalConfig, outputdir: str
7495
) -> None:
@@ -92,8 +113,9 @@ def _modify_and_replace_token_for_oauth_templates(
92113
s = f.read()
93114

94115
with open(os.path.join(html_template_path, "redirect.html"), "w") as f:
95-
s = s.replace("${ta.name}", ta_name.lower())
96-
s = s.replace("${ta.version}", global_config.version)
116+
s = s.replace("__APP_NAME__", ta_name)
117+
s = s.replace("__TA_NAME__", ta_name.lower())
118+
s = s.replace("__TA_VERSION__", global_config.version)
97119
f.write(s)
98120

99121
redirect_js_dest = (
@@ -608,11 +630,6 @@ def generate(
608630
if global_config.has_pages():
609631
builder_obj = RestBuilder(scheme, os.path.join(output_directory, ta_name))
610632
builder_obj.build()
611-
_modify_and_replace_token_for_oauth_templates(
612-
ta_name,
613-
global_config,
614-
output_directory,
615-
)
616633
if global_config.has_inputs():
617634
logger.info("Generating inputs code")
618635
_add_modular_input(ta_name, global_config, output_directory, gc_path)
@@ -646,6 +663,17 @@ def generate(
646663
utils.recursive_overwrite(source, os.path.join(output_directory, ta_name))
647664
logger.info("Copied package directory")
648665

666+
# Apply template placeholder replacement on the final copied output.
667+
# Running this before recursive_overwrite causes package templates to
668+
# overwrite the transformed files and leaves placeholders behind.
669+
if global_config.has_pages():
670+
_modify_and_replace_token_for_oauth_templates(
671+
ta_name,
672+
global_config,
673+
output_directory,
674+
)
675+
_inject_app_name_in_base_html(ta_name, output_directory)
676+
649677
default_meta_conf_path = os.path.join(
650678
output_directory, ta_name, "metadata", meta_conf_lib.DEFAULT_META_FILE_NAME
651679
)

splunk_add_on_ucc_framework/package/appserver/templates/base.html

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,38 @@
1414
~ limitations under the License.
1515
~
1616
-->
17-
<%!
18-
from splunk.appserver.mrsparkle.lib import util
19-
20-
app_name = cherrypy.request.path_info.split('/')[3]
21-
%>\
2217
<!DOCTYPE html>
2318
<html class="no-js" lang="">
2419
<head>
2520
<meta charset="utf-8" />
2621
<meta http-equiv="x-ua-compatible" content="ie=edge" />
27-
<title>${_('Loading')}</title>
22+
<title>Loading</title>
2823
<meta name="viewport" content="width=device-width, initial-scale=1" />
29-
<link rel="shortcut icon" href="${util.getFaviconURL()}" />
30-
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
31-
<base >
24+
<script src="../../config?autoload=1" crossorigin="use-credentials"></script>
3225
</head>
3326

3427
<body>
35-
<script src="${make_url('/config?autoload=1')}" crossorigin="use-credentials"></script>
36-
<script src="${make_url('/static/js/i18n.js')}"></script>
37-
<script src="${make_url('/i18ncatalog?autoload=1')}"></script>
3828
<script>
39-
__splunkd_partials__ = ${json_decode(splunkd)};
29+
var _b = window.$C && window.$C.BUILD_NUMBER ? '/@' + window.$C.BUILD_NUMBER : '';
30+
var _p = _b && window.$C.BUILD_PUSH_NUMBER ? '.' + window.$C.BUILD_PUSH_NUMBER : '';
31+
function _loadScript(src, type) {
32+
return new Promise(function (resolve, reject) {
33+
var s = document.createElement('script');
34+
if (type) s.type = type;
35+
s.src = src;
36+
s.onload = resolve;
37+
s.onerror = reject;
38+
document.head.appendChild(s);
39+
});
40+
}
41+
_loadScript('../../static' + _b + _p + '/js/i18n.js')
42+
.then(function () { return _loadScript('../../i18ncatalog?autoload=1'); })
43+
.then(function () {
44+
return _loadScript(
45+
'../../static' + _b + _p + '/app/__APP_NAME__/js/build/entry_page.js',
46+
'module'
47+
);
48+
});
4049
</script>
41-
42-
<% page_path = "/static/app/" + app_name + "/js/build/entry_page.js" %>
43-
44-
<script type="module" src="${make_url(page_path)}"></script>
4550
</body>
4651
</html>

splunk_add_on_ucc_framework/package/appserver/templates/redirect.html

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,38 @@
1414
~ limitations under the License.
1515
~
1616
-->
17-
<%! app_name = cherrypy.request.path_info.split('/')[3] %>\
1817
<!DOCTYPE html>
1918
<html class="no-js" lang="">
2019
<head>
2120
<meta charset="utf-8" />
2221
<meta http-equiv="x-ua-compatible" content="ie=edge" />
23-
<title>${_('Loading')}</title>
22+
<title>Loading</title>
2423
<meta name="viewport" content="width=device-width, initial-scale=1" />
25-
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
24+
<script src="../../config?autoload=1" crossorigin="use-credentials"></script>
2625
</head>
2726

2827
<body>
29-
<script src="${make_url('/config?autoload=1')}" crossorigin="use-credentials"></script>
30-
<script src="${make_url('/static/js/i18n.js')}"></script>
31-
<script src="${make_url('/i18ncatalog?autoload=1')}"></script>
3228
<script>
33-
__splunkd_partials__ = ${json_decode(splunkd)};
29+
var _b = window.$C && window.$C.BUILD_NUMBER ? '/@' + window.$C.BUILD_NUMBER : '';
30+
var _p = _b && window.$C.BUILD_PUSH_NUMBER ? '.' + window.$C.BUILD_PUSH_NUMBER : '';
31+
function _loadScript(src, type) {
32+
return new Promise(function (resolve, reject) {
33+
var s = document.createElement('script');
34+
if (type) s.type = type;
35+
s.src = src;
36+
s.onload = resolve;
37+
s.onerror = reject;
38+
document.head.appendChild(s);
39+
});
40+
}
41+
_loadScript('../../static' + _b + _p + '/js/i18n.js')
42+
.then(function () { return _loadScript('../../i18ncatalog?autoload=1'); })
43+
.then(function () {
44+
return _loadScript(
45+
'../../static' + _b + _p + '/app/__APP_NAME__/js/build/__TA_NAME___redirect_page.__TA_VERSION__.js',
46+
'module'
47+
);
48+
});
3449
</script>
35-
36-
<% page_path = "/static/app/" + app_name + "/js/build/${ta.name}_redirect_page.${ta.version}.js" %>
37-
38-
<script type="module" src="${make_url(page_path)}"></script>
3950
</body>
4051
</html>

splunk_add_on_ucc_framework/package_files_update.py

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,85 @@
1414
# limitations under the License.
1515
#
1616
import logging
17-
import os
18-
import re
19-
from collections import namedtuple
2017
from pathlib import Path
21-
from typing import Optional
18+
from typing import Callable
2219

2320
logger = logging.getLogger("ucc_gen")
24-
FileUpdater = namedtuple("FileUpdater", ["path_segments", "function"])
2521

22+
internal_root_dir = Path(__file__).resolve().parent
2623

27-
_base_html_pattern = re.compile(
28-
r"<script\s+src=\"\${make_url\(page_path\)}\"\s*>\s*</script>"
29-
)
3024

25+
def _load_canonical_template(template_name: str) -> str:
26+
return (
27+
internal_root_dir / "package" / "appserver" / "templates" / template_name
28+
).read_text()
3129

32-
def _handle_base_html_update(content: str) -> Optional[str]:
33-
matches = _base_html_pattern.findall(content)
3430

35-
if not matches:
36-
return None
31+
def _is_legacy_base_html(content: str) -> bool:
32+
legacy_markers = (
33+
"cherrypy.request.path_info",
34+
"${make_url('/config?autoload=1')}",
35+
"__splunkd_partials__ = ${json_decode(splunkd)};",
36+
'<script type="module" src="${make_url(page_path)}"></script>',
37+
'<script src="${make_url(page_path)}"></script>',
38+
'page_path = "/static/app/" + app_name + "/js/build/entry_page.js"',
39+
)
40+
return any(marker in content for marker in legacy_markers)
3741

38-
for result in matches:
39-
content = content.replace(
40-
result, '<script type="module" src="${make_url(page_path)}"></script>'
41-
)
4242

43-
return content
43+
def _is_legacy_redirect_html(content: str) -> bool:
44+
legacy_markers = (
45+
"cherrypy.request.path_info",
46+
"${make_url('/config?autoload=1')}",
47+
"__splunkd_partials__ = ${json_decode(splunkd)};",
48+
"${ta.name}",
49+
"${ta.version}",
50+
'page_path = "/static/app/" + app_name + "/js/build/${ta.name}_redirect_page.${ta.version}.js"',
51+
)
52+
return any(marker in content for marker in legacy_markers)
4453

4554

46-
def handle_package_files_update(path: str) -> None:
47-
files_to_update = [
48-
FileUpdater(("appserver", "templates", "base.html"), _handle_base_html_update)
49-
]
55+
def _migrate_template_if_needed(
56+
package_dir: str,
57+
relative_path: str,
58+
template_name: str,
59+
detector: Callable[[str], bool],
60+
) -> None:
61+
file_path = Path(package_dir) / relative_path
62+
if not file_path.is_file():
63+
return
5064

51-
for file_updater in files_to_update:
52-
relative_path = os.path.join(*file_updater.path_segments)
53-
file_path = os.path.join(path, *file_updater.path_segments)
65+
current_content = file_path.read_text()
66+
if current_content == _load_canonical_template(template_name):
67+
return
5468

55-
if not os.path.isfile(file_path):
56-
continue
69+
if detector(current_content):
70+
file_path.write_text(_load_canonical_template(template_name))
71+
logger.info(
72+
"File '%s' exists in the package directory and was updated to the "
73+
"current static UCC template to remove legacy Mako/CherryPy usage.",
74+
relative_path,
75+
)
76+
return
5777

58-
path_obj = Path(file_path)
59-
original_content = path_obj.read_text()
60-
output_content = file_updater.function(original_content)
78+
logger.warning(
79+
"File '%s' exists in the package directory and uses a custom template. "
80+
"UCC left it unchanged because it could not be safely migrated "
81+
"automatically.",
82+
relative_path,
83+
)
6184

62-
if output_content is None or original_content == output_content:
63-
continue
6485

65-
path_obj.write_text(output_content)
66-
logger.info(
67-
f"File '{relative_path}' exists in the package directory and its content needed to be updated by UCC."
68-
)
86+
def handle_package_files_update(path: str) -> None:
87+
_migrate_template_if_needed(
88+
path,
89+
"appserver/templates/base.html",
90+
"base.html",
91+
_is_legacy_base_html,
92+
)
93+
_migrate_template_if_needed(
94+
path,
95+
"appserver/templates/redirect.html",
96+
"redirect.html",
97+
_is_legacy_redirect_html,
98+
)

0 commit comments

Comments
 (0)