besapi 3.9.4__tar.gz → 3.9.6__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.
- {besapi-3.9.4/src/besapi.egg-info → besapi-3.9.6}/PKG-INFO +1 -1
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/besapi.py +2 -1
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/plugin_utilities.py +11 -1
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/plugin_utilities_win.py +8 -11
- {besapi-3.9.4 → besapi-3.9.6/src/besapi.egg-info}/PKG-INFO +1 -1
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi.egg-info/SOURCES.txt +2 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/bescli/bescli.py +1 -1
- besapi-3.9.6/tests/test_plugin_utilities.py +60 -0
- besapi-3.9.6/tests/test_plugin_utilities_logging.py +61 -0
- {besapi-3.9.4 → besapi-3.9.6}/LICENSE.txt +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/MANIFEST.in +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/README.md +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/pyproject.toml +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/setup.cfg +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/setup.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/__init__.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/__main__.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/schemas/BES.xsd +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/schemas/BESAPI.xsd +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi/schemas/BESActionSettings.xsd +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi.egg-info/dependency_links.txt +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi.egg-info/requires.txt +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/besapi.egg-info/top_level.txt +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/bescli/__init__.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/src/bescli/__main__.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/tests/test_besapi.py +0 -0
- {besapi-3.9.4 → besapi-3.9.6}/tests/tests.py +0 -0
|
@@ -4,6 +4,7 @@ This module besapi provides a simple interface to the BigFix REST API.
|
|
|
4
4
|
|
|
5
5
|
MIT License
|
|
6
6
|
Copyright (c) 2014 Matt Hansen
|
|
7
|
+
Copyright (c) 2021 James Stewart
|
|
7
8
|
Maintained by James Stewart since 2021
|
|
8
9
|
|
|
9
10
|
Library for communicating with the BES (BigFix) REST API.
|
|
@@ -25,7 +26,7 @@ import lxml.etree
|
|
|
25
26
|
import lxml.objectify
|
|
26
27
|
import requests
|
|
27
28
|
|
|
28
|
-
__version__ = "3.9.
|
|
29
|
+
__version__ = "3.9.6"
|
|
29
30
|
|
|
30
31
|
besapi_logger = logging.getLogger("besapi")
|
|
31
32
|
|
|
@@ -14,6 +14,9 @@ from typing import Union
|
|
|
14
14
|
|
|
15
15
|
import besapi
|
|
16
16
|
|
|
17
|
+
if os.name == "nt":
|
|
18
|
+
import besapi.plugin_utilities_win
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
# NOTE: This does not work as expected when run from plugin_utilities
|
|
19
22
|
def get_invoke_folder(verbose=0):
|
|
@@ -92,6 +95,13 @@ def setup_plugin_argparse(plugin_args_required=False):
|
|
|
92
95
|
return arg_parser
|
|
93
96
|
|
|
94
97
|
|
|
98
|
+
def get_plugin_args(plugin_args_required=False):
|
|
99
|
+
"""Get basic args for plugin use."""
|
|
100
|
+
arg_parser = setup_plugin_argparse(plugin_args_required)
|
|
101
|
+
args, _unknown = arg_parser.parse_known_args()
|
|
102
|
+
return args
|
|
103
|
+
|
|
104
|
+
|
|
95
105
|
def get_plugin_logging_config(log_file_path="", verbose=0, console=True):
|
|
96
106
|
"""Get config for logging for plugin use.
|
|
97
107
|
|
|
@@ -208,7 +218,7 @@ def get_besapi_connection_args(
|
|
|
208
218
|
"attempts to connect to BigFix using rest_url and besserver both failed"
|
|
209
219
|
)
|
|
210
220
|
return None
|
|
211
|
-
except BaseException as err:
|
|
221
|
+
except BaseException as err: # pylint: disable=broad-exception-caught
|
|
212
222
|
# always log error
|
|
213
223
|
logging.exception("ERROR: %s", err)
|
|
214
224
|
logging.exception(
|
|
@@ -23,7 +23,7 @@ except (ImportError, ModuleNotFoundError) as e:
|
|
|
23
23
|
raise e
|
|
24
24
|
|
|
25
25
|
try:
|
|
26
|
-
import win32crypt
|
|
26
|
+
import win32crypt # type: ignore[import]
|
|
27
27
|
except (ImportError, ModuleNotFoundError) as e:
|
|
28
28
|
if not sys.platform.startswith("win"):
|
|
29
29
|
raise RuntimeError("This script only works on Windows systems") from e
|
|
@@ -141,7 +141,7 @@ def win_registry_value_read(hive, subkey, value_name):
|
|
|
141
141
|
except FileNotFoundError:
|
|
142
142
|
logger.debug("Registry key or value '%s\\%s' not found.", subkey, value_name)
|
|
143
143
|
return None
|
|
144
|
-
except Exception as e:
|
|
144
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
145
145
|
logger.error("An error occurred: %s", e)
|
|
146
146
|
return None
|
|
147
147
|
|
|
@@ -203,14 +203,11 @@ def get_besconn_root_windows_registry() -> Union[besapi.besapi.BESConnection, No
|
|
|
203
203
|
return None
|
|
204
204
|
|
|
205
205
|
# normalize url to https://HostOrIP:52311
|
|
206
|
-
if rest_url
|
|
206
|
+
if rest_url.endswith("/api"):
|
|
207
207
|
rest_url = rest_url.replace("/api", "")
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return None
|
|
215
|
-
|
|
216
|
-
return None
|
|
209
|
+
try:
|
|
210
|
+
return besapi.besapi.BESConnection(user, password, rest_url)
|
|
211
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
212
|
+
logger.error("Failed to create BESConnection from registry values: %s", e)
|
|
213
|
+
return None
|
|
@@ -500,7 +500,7 @@ class BESCLInterface(Cmd):
|
|
|
500
500
|
def do_update_item(self, file_path):
|
|
501
501
|
"""Update bigfix content item from bes file."""
|
|
502
502
|
if not os.access(file_path, os.R_OK):
|
|
503
|
-
self.poutput(file_path, "is not a readable file")
|
|
503
|
+
self.poutput(file_path, " is not a readable file")
|
|
504
504
|
else:
|
|
505
505
|
self.poutput(self.bes_conn.update_item_from_file(file_path))
|
|
506
506
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
# Ensure the local `src/` is first on sys.path so tests import the workspace package
|
|
7
|
+
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
8
|
+
SRC = os.path.join(ROOT, "src")
|
|
9
|
+
if SRC not in sys.path:
|
|
10
|
+
sys.path.insert(0, SRC)
|
|
11
|
+
|
|
12
|
+
from besapi import plugin_utilities
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_setup_plugin_argparse_defaults():
|
|
16
|
+
"""Test that default args are set correctly."""
|
|
17
|
+
parser = plugin_utilities.setup_plugin_argparse(plugin_args_required=False)
|
|
18
|
+
# ensure parser returns expected arguments when not required
|
|
19
|
+
args = parser.parse_args([])
|
|
20
|
+
assert args.verbose == 0
|
|
21
|
+
assert args.console is False
|
|
22
|
+
assert args.besserver is None
|
|
23
|
+
assert args.rest_url is None
|
|
24
|
+
assert args.user is None
|
|
25
|
+
assert args.password is None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_setup_plugin_argparse_required_flags():
|
|
29
|
+
"""Test that required args cause SystemExit when missing."""
|
|
30
|
+
parser = plugin_utilities.setup_plugin_argparse(plugin_args_required=True)
|
|
31
|
+
# when required, missing required args should cause SystemExit
|
|
32
|
+
with pytest.raises(SystemExit):
|
|
33
|
+
parser.parse_args([])
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_get_plugin_args_parses_known_args(monkeypatch):
|
|
37
|
+
"""Test that known command line args are parsed correctly."""
|
|
38
|
+
# simulate command line args
|
|
39
|
+
monkeypatch.setattr(
|
|
40
|
+
sys,
|
|
41
|
+
"argv",
|
|
42
|
+
[
|
|
43
|
+
"prog",
|
|
44
|
+
"-v",
|
|
45
|
+
"-c",
|
|
46
|
+
"--rest-url",
|
|
47
|
+
"https://example:52311",
|
|
48
|
+
"--user",
|
|
49
|
+
"me",
|
|
50
|
+
"--password",
|
|
51
|
+
"pw",
|
|
52
|
+
],
|
|
53
|
+
)
|
|
54
|
+
args = plugin_utilities.get_plugin_args(plugin_args_required=False)
|
|
55
|
+
assert args.verbose == 1
|
|
56
|
+
assert args.console is True
|
|
57
|
+
assert args.rest_url == "https://example:52311"
|
|
58
|
+
assert args.user == "me"
|
|
59
|
+
assert args.password == "pw"
|
|
60
|
+
assert args.besserver is None
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import tempfile
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from besapi import plugin_utilities
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_get_plugin_logging_config_default(tmp_path, capsys):
|
|
11
|
+
"""Test default logging config with no verbosity and no console."""
|
|
12
|
+
# Use an explicit log file path in a temp dir to avoid touching real files
|
|
13
|
+
log_file = tmp_path / "test.log"
|
|
14
|
+
|
|
15
|
+
cfg = plugin_utilities.get_plugin_logging_config(
|
|
16
|
+
str(log_file), verbose=0, console=False
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# handlers should include a RotatingFileHandler only
|
|
20
|
+
handlers = cfg.get("handlers")
|
|
21
|
+
assert handlers, "handlers should be present"
|
|
22
|
+
assert len(handlers) == 1
|
|
23
|
+
assert isinstance(handlers[0], logging.handlers.RotatingFileHandler)
|
|
24
|
+
|
|
25
|
+
# level should be WARNING when verbose=0
|
|
26
|
+
assert cfg.get("level") == logging.WARNING
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_get_plugin_logging_config_verbose_and_console(tmp_path, capsys):
|
|
30
|
+
"""Test logging config with verbosity and console logging."""
|
|
31
|
+
# ensure the function prints info when verbose and console True
|
|
32
|
+
log_file = tmp_path / "test2.log"
|
|
33
|
+
|
|
34
|
+
cfg = plugin_utilities.get_plugin_logging_config(
|
|
35
|
+
str(log_file), verbose=1, console=True
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
handlers = cfg.get("handlers")
|
|
39
|
+
# should have file handler + stream handler
|
|
40
|
+
assert any(isinstance(h, logging.handlers.RotatingFileHandler) for h in handlers)
|
|
41
|
+
assert any(isinstance(h, logging.StreamHandler) for h in handlers)
|
|
42
|
+
|
|
43
|
+
# verbose=1 -> INFO
|
|
44
|
+
assert cfg.get("level") == logging.INFO
|
|
45
|
+
|
|
46
|
+
# get printed output
|
|
47
|
+
captured = capsys.readouterr()
|
|
48
|
+
assert "INFO: Log File Path:" in captured.out
|
|
49
|
+
assert "INFO: also logging to console" in captured.out
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_get_plugin_logging_config_debug_level(tmp_path):
|
|
53
|
+
"""Test logging config with debug level verbosity."""
|
|
54
|
+
log_file = tmp_path / "test3.log"
|
|
55
|
+
|
|
56
|
+
cfg = plugin_utilities.get_plugin_logging_config(
|
|
57
|
+
str(log_file), verbose=2, console=False
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# verbose>1 -> DEBUG
|
|
61
|
+
assert cfg.get("level") == logging.DEBUG
|
|
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
|