solnlib 8.2.0b1__tar.gz → 8.2.1b1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/PKG-INFO +1 -1
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/pyproject.toml +1 -1
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/__init__.py +1 -1
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/observability.py +30 -18
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/splunkenv.py +62 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/LICENSE +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/_observability_flush.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/_settings.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/_utils.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/acl.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/alerts_rest_client.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/bulletin_rest_client.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/concurrent/concurrent_executor.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/concurrent/process_pool.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/concurrent/thread_pool.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/conf_manager.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/credentials.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/file_monitor.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/hec_config.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/log.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/__init__.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/checkpointer.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/event.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/event_writer.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/modinput.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/modular_input/modular_input.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/net_utils.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/orphan_process_monitor.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/pattern.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/rest.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/schedule/job.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/schedule/scheduler.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/server_info.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/soln_exceptions.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/splunk_rest_client.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/time_parser.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/timer_queue.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/user_access.py +0 -0
- {solnlib-8.2.0b1 → solnlib-8.2.1b1}/solnlib/utils.py +0 -0
|
@@ -53,7 +53,7 @@ import threading
|
|
|
53
53
|
import urllib.request
|
|
54
54
|
from typing import Callable, ClassVar, Optional, Union
|
|
55
55
|
from ._observability_flush import _register_controller
|
|
56
|
-
from .splunkenv import get_conf_stanzas
|
|
56
|
+
from .splunkenv import _get_running_app_name, get_conf_stanzas
|
|
57
57
|
from opentelemetry.metrics import Instrument, Meter
|
|
58
58
|
from opentelemetry.sdk.metrics import MeterProvider, Counter, Histogram
|
|
59
59
|
from opentelemetry.sdk.metrics.export import (
|
|
@@ -392,12 +392,14 @@ class ObservabilityService:
|
|
|
392
392
|
logger: Python logger (or ``LoggerAdapter``) for all diagnostic
|
|
393
393
|
output. Typically the caller's own module-level logger.
|
|
394
394
|
ta_name: Add-on identifier, e.g. ``"Splunk_TA_myapp"``. When
|
|
395
|
-
*None* the value is read from the ``[id]`` stanza of
|
|
396
|
-
``app.conf``
|
|
397
|
-
|
|
398
|
-
|
|
395
|
+
*None* the value is read from the ``[id]`` stanza of the
|
|
396
|
+
``app.conf`` of the running app (detected from the main
|
|
397
|
+
script's path, then solnlib's own path; falling back to the
|
|
398
|
+
app directory name).
|
|
399
|
+
Pass it explicitly when the add-on runs outside a standard
|
|
400
|
+
``etc/apps/<app>`` layout or to avoid the ``app.conf`` lookup.
|
|
399
401
|
ta_version: Add-on version string, e.g. ``"3.1.0"``. When *None*
|
|
400
|
-
the value is read from the ``[launcher]`` stanza of
|
|
402
|
+
the value is read from the ``[launcher]`` stanza of the same
|
|
401
403
|
``app.conf``. Falls back to ``"unknown"`` if it cannot be
|
|
402
404
|
determined.
|
|
403
405
|
extra_exporters: Optional list of additional
|
|
@@ -433,8 +435,8 @@ class ObservabilityService:
|
|
|
433
435
|
|
|
434
436
|
if not ta_name:
|
|
435
437
|
raise ValueError(
|
|
436
|
-
"ta_name could not be determined: pass it explicitly or
|
|
437
|
-
"
|
|
438
|
+
"ta_name could not be determined: pass it explicitly or run "
|
|
439
|
+
"the add-on from etc/apps/<app>"
|
|
438
440
|
)
|
|
439
441
|
|
|
440
442
|
resource = Resource(
|
|
@@ -504,19 +506,29 @@ class ObservabilityService:
|
|
|
504
506
|
)
|
|
505
507
|
|
|
506
508
|
def _read_ta_info(self) -> tuple[Optional[str], Optional[str]]:
|
|
507
|
-
"""Read the add-on name and version from ``app.conf``.
|
|
509
|
+
"""Read the add-on name and version from the owning app's ``app.conf``.
|
|
508
510
|
|
|
509
|
-
|
|
510
|
-
``
|
|
511
|
-
|
|
511
|
+
The owning app is the one whose script is running
|
|
512
|
+
(``etc/apps/<app>/bin/...``), or failing that the one that bundles
|
|
513
|
+
solnlib. The lookup is always scoped to that app: an unscoped
|
|
514
|
+
``app.conf`` merge can return another installed add-on's ``[id]``
|
|
515
|
+
stanza.
|
|
516
|
+
|
|
517
|
+
Returns a ``(ta_name, ta_version)`` tuple. Both are ``None`` when the
|
|
518
|
+
owning app cannot be detected or ``app.conf`` cannot be read; the
|
|
519
|
+
version alone is ``None`` when ``[launcher] version`` is missing.
|
|
512
520
|
"""
|
|
513
521
|
try:
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
522
|
+
app_name = _get_running_app_name()
|
|
523
|
+
if not app_name:
|
|
524
|
+
self._logger.info(
|
|
525
|
+
"Could not determine the running add-on from the script "
|
|
526
|
+
"or solnlib path; app.conf not read"
|
|
527
|
+
)
|
|
528
|
+
return None, None
|
|
529
|
+
stanzas = get_conf_stanzas("app", app_name=app_name)
|
|
530
|
+
ta_name = stanzas.get("id", {}).get("name") or app_name
|
|
531
|
+
ta_version = stanzas.get("launcher", {}).get("version") or None
|
|
520
532
|
return ta_name, ta_version
|
|
521
533
|
except Exception as error:
|
|
522
534
|
self._logger.info(
|
|
@@ -19,9 +19,11 @@ import os
|
|
|
19
19
|
import os.path as op
|
|
20
20
|
import socket
|
|
21
21
|
import subprocess
|
|
22
|
+
import sys
|
|
22
23
|
import json
|
|
23
24
|
from configparser import ConfigParser
|
|
24
25
|
from io import StringIO
|
|
26
|
+
from pathlib import Path
|
|
25
27
|
from typing import Optional, Union
|
|
26
28
|
import __main__
|
|
27
29
|
from solnlib._settings import use_btool
|
|
@@ -66,6 +68,7 @@ __all__ = [
|
|
|
66
68
|
ETC_LEAF = "etc"
|
|
67
69
|
APP_SYSTEM = "system"
|
|
68
70
|
APP_HEC = "splunk_httpinput"
|
|
71
|
+
_APPS_DIRS = ("apps", "peer-apps", "slave-apps")
|
|
69
72
|
|
|
70
73
|
|
|
71
74
|
class SessionKeyNotFound(Exception):
|
|
@@ -92,6 +95,65 @@ def make_splunkhome_path(parts: Union[list, tuple]) -> str:
|
|
|
92
95
|
return msp(parts)
|
|
93
96
|
|
|
94
97
|
|
|
98
|
+
def _is_splunk_etc_dir(path: Path) -> bool:
|
|
99
|
+
if op.normcase(path.name) == ETC_LEAF:
|
|
100
|
+
return True
|
|
101
|
+
splunk_etc = os.environ.get("SPLUNK_ETC")
|
|
102
|
+
return bool(splunk_etc) and op.normcase(op.realpath(splunk_etc)) == op.normcase(
|
|
103
|
+
op.realpath(path)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _get_app_name_from_path(path: str) -> Optional[str]:
|
|
108
|
+
"""Return the name of the Splunk app that contains `path`.
|
|
109
|
+
|
|
110
|
+
The app is the directory directly under ``$SPLUNK_ETC/apps`` (or
|
|
111
|
+
``peer-apps`` / ``slave-apps`` on indexer cluster peers). For example,
|
|
112
|
+
``$SPLUNK_HOME/etc/apps/Splunk_TA_test/bin/input.py`` resolves to
|
|
113
|
+
``"Splunk_TA_test"``.
|
|
114
|
+
|
|
115
|
+
Arguments:
|
|
116
|
+
path: File system path to inspect.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
App name, or None if `path` is not inside a Splunk apps directory.
|
|
120
|
+
"""
|
|
121
|
+
# Not utils.get_appname_from_path: that one returns "-", ignores
|
|
122
|
+
# SPLUNK_ETC and slave-apps, and is public, so its behaviour is kept.
|
|
123
|
+
try:
|
|
124
|
+
# abspath, not resolve(): apps symlinked into etc/apps keep their name.
|
|
125
|
+
absolute = Path(op.abspath(path))
|
|
126
|
+
# Outermost match first: Splunk's etc/apps sits above anything an app
|
|
127
|
+
# vendors that happens to contain etc/apps.
|
|
128
|
+
for candidate in reversed((absolute, *absolute.parents)):
|
|
129
|
+
parent = candidate.parent
|
|
130
|
+
if op.normcase(parent.name) in _APPS_DIRS and _is_splunk_etc_dir(
|
|
131
|
+
parent.parent
|
|
132
|
+
):
|
|
133
|
+
return candidate.name
|
|
134
|
+
except (OSError, ValueError):
|
|
135
|
+
pass
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _get_running_app_name() -> Optional[str]:
|
|
140
|
+
"""Return the name of the Splunk app whose script is running.
|
|
141
|
+
|
|
142
|
+
Tries the main script first (modular inputs, alert actions and search
|
|
143
|
+
commands run from ``etc/apps/<app>/bin``; this path also keeps
|
|
144
|
+
symlinked app directories intact), then falls back to the app that
|
|
145
|
+
bundles solnlib.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
App name, or None if neither path is inside a Splunk apps directory.
|
|
149
|
+
"""
|
|
150
|
+
argv = getattr(sys, "argv", None)
|
|
151
|
+
main_path = getattr(__main__, "__file__", None) or (argv[0] if argv else None)
|
|
152
|
+
return (main_path and _get_app_name_from_path(main_path)) or (
|
|
153
|
+
_get_app_name_from_path(__file__)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
95
157
|
def get_splunk_host_info(session_key: Optional[str] = None) -> tuple:
|
|
96
158
|
"""Get splunk host info.
|
|
97
159
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|