mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 09:12:45 +01:00
add yaml helper script; refactor python testing
This commit is contained in:
22
pyci.sh
Executable file
22
pyci.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
echo "Usage: $0 <python_script_dir>"
|
||||||
|
echo "Runs tests on all *_test.py files in the given directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
HOME_DIR=$(dirname "$0")
|
||||||
|
TARGET_DIR=${1:-.}
|
||||||
|
|
||||||
|
PATH=$PATH:/usr/local/bin
|
||||||
|
|
||||||
|
if ! which pytest &> /dev/null || ! which flake8 &> /dev/null ; then
|
||||||
|
echo "Missing dependencies. Consider running the following command:"
|
||||||
|
echo " python -m pip install flake8 pytest pytest-cov"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
pip install pytest pytest-cov
|
||||||
|
flake8 "$TARGET_DIR" "--config=${HOME_DIR}/pytest.ini"
|
||||||
|
python3 -m pytest "--cov-config=${HOME_DIR}/pytest.ini" "--cov=$TARGET_DIR" --doctest-modules --cov-report=term --cov-fail-under=100 "$TARGET_DIR"
|
||||||
@@ -1,19 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Copyright 2014-2023 Security Onion Solutions, LLC
|
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
||||||
#
|
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# it under the terms of the GNU General Public License as published by
|
# Elastic License 2.0.
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|||||||
97
salt/manager/tools/sbin/so-yaml.py
Executable file
97
salt/manager/tools/sbin/so-yaml.py
Executable file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
||||||
|
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
||||||
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
|
# Elastic License 2.0.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
lockFile = "/tmp/so-yaml.lock"
|
||||||
|
|
||||||
|
|
||||||
|
def showUsage(args):
|
||||||
|
print('Usage: {} <COMMAND> <YAML_FILE> [ARGS...]'.format(sys.argv[0]))
|
||||||
|
print(' General commands:')
|
||||||
|
print(' remove - Removes a yaml top-level key, if it exists. Requires KEY arg.')
|
||||||
|
print(' help - Prints this usage information.')
|
||||||
|
print('')
|
||||||
|
print(' Where:')
|
||||||
|
print(' YAML_FILE - Path to the file that will be modified. Ex: /opt/so/conf/service/conf.yaml')
|
||||||
|
print(' KEY - Top level key only, does not support dot-notations for nested keys at this time. Ex: level1')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def loadYaml(filename):
|
||||||
|
file = open(filename, "r")
|
||||||
|
content = file.read()
|
||||||
|
return yaml.safe_load(content)
|
||||||
|
|
||||||
|
|
||||||
|
def writeYaml(filename, content):
|
||||||
|
file = open(filename, "w")
|
||||||
|
return yaml.dump(content, file)
|
||||||
|
|
||||||
|
|
||||||
|
def remove(args):
|
||||||
|
if len(args) != 2:
|
||||||
|
print('Missing filename or key arg', file=sys.stderr)
|
||||||
|
showUsage(None)
|
||||||
|
return
|
||||||
|
|
||||||
|
filename = args[0]
|
||||||
|
content = loadYaml(filename)
|
||||||
|
|
||||||
|
content.pop(args[1], None)
|
||||||
|
|
||||||
|
writeYaml(filename, content)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = sys.argv[1:]
|
||||||
|
|
||||||
|
if len(args) < 1:
|
||||||
|
showUsage(None)
|
||||||
|
return
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
"help": showUsage,
|
||||||
|
"remove": remove,
|
||||||
|
}
|
||||||
|
|
||||||
|
code = 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
lockAttempts = 0
|
||||||
|
maxAttempts = 30
|
||||||
|
while lockAttempts < maxAttempts:
|
||||||
|
lockAttempts = lockAttempts + 1
|
||||||
|
try:
|
||||||
|
f = open(lockFile, "x")
|
||||||
|
f.close()
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
if lockAttempts == 1:
|
||||||
|
print("Waiting for lock file to be released from another process...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
if lockAttempts == maxAttempts:
|
||||||
|
print("Lock file (" + lockFile + ") could not be created; proceeding without lock.")
|
||||||
|
|
||||||
|
cmd = commands.get(args[0], showUsage)
|
||||||
|
code = cmd(args[1:])
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
os.remove(lockFile)
|
||||||
|
except Exception:
|
||||||
|
print("Lock file (" + lockFile + ") already removed")
|
||||||
|
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
59
salt/manager/tools/sbin/so-yaml_test.py
Normal file
59
salt/manager/tools/sbin/so-yaml_test.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
from io import StringIO
|
||||||
|
import sys
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
import unittest
|
||||||
|
import importlib
|
||||||
|
soyaml = importlib.import_module("so-yaml")
|
||||||
|
|
||||||
|
|
||||||
|
class TestRemove(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_main_missing_input(self):
|
||||||
|
with patch('sys.exit', new=MagicMock()) as sysmock:
|
||||||
|
with patch('sys.stderr', new=StringIO()) as mock_stdout:
|
||||||
|
sys.argv = ["cmd"]
|
||||||
|
soyaml.main()
|
||||||
|
sysmock.assert_called_once_with(1)
|
||||||
|
self.assertIn(mock_stdout.getvalue(), "Usage:")
|
||||||
|
|
||||||
|
def test_main_help(self):
|
||||||
|
with patch('sys.exit', new=MagicMock()) as sysmock:
|
||||||
|
with patch('sys.stderr', new=StringIO()) as mock_stdout:
|
||||||
|
sys.argv = ["cmd", "help"]
|
||||||
|
soyaml.main()
|
||||||
|
sysmock.assert_called()
|
||||||
|
self.assertIn(mock_stdout.getvalue(), "Usage:")
|
||||||
|
|
||||||
|
def test_remove(self):
|
||||||
|
filename = "/tmp/so-yaml_test-remove.yaml"
|
||||||
|
file = open(filename, "w")
|
||||||
|
file.write("{key1: { child1: 123, child2: abc }, key2: false}")
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
soyaml.remove([filename, "key1"])
|
||||||
|
|
||||||
|
file = open(filename, "r")
|
||||||
|
actual = file.read()
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
expected = "key2: false\n"
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_remove_missing_args(self):
|
||||||
|
with patch('sys.exit', new=MagicMock()) as sysmock:
|
||||||
|
with patch('sys.stderr', new=StringIO()) as mock_stdout:
|
||||||
|
filename = "/tmp/so-yaml_test-remove.yaml"
|
||||||
|
file = open(filename, "w")
|
||||||
|
file.write("{key1: { child1: 123, child2: abc }, key2: false}")
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
soyaml.remove([filename])
|
||||||
|
|
||||||
|
file = open(filename, "r")
|
||||||
|
actual = file.read()
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
expected = "{key1: { child1: 123, child2: abc }, key2: false}"
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
sysmock.assert_called_once_with(1)
|
||||||
|
self.assertIn(mock_stdout.getvalue(), "Missing filename or key arg\n")
|
||||||
@@ -3,23 +3,6 @@
|
|||||||
COMMAND=$1
|
COMMAND=$1
|
||||||
SENSORONI_CONTAINER=${SENSORONI_CONTAINER:-so-sensoroni}
|
SENSORONI_CONTAINER=${SENSORONI_CONTAINER:-so-sensoroni}
|
||||||
|
|
||||||
function ci() {
|
|
||||||
HOME_DIR=$(dirname "$0")
|
|
||||||
TARGET_DIR=${1:-.}
|
|
||||||
|
|
||||||
PATH=$PATH:/usr/local/bin
|
|
||||||
|
|
||||||
if ! which pytest &> /dev/null || ! which flake8 &> /dev/null ; then
|
|
||||||
echo "Missing dependencies. Consider running the following command:"
|
|
||||||
echo " python -m pip install flake8 pytest pytest-cov"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
pip install pytest pytest-cov
|
|
||||||
flake8 "$TARGET_DIR" "--config=${HOME_DIR}/pytest.ini"
|
|
||||||
python3 -m pytest "--cov-config=${HOME_DIR}/pytest.ini" "--cov=$TARGET_DIR" --doctest-modules --cov-report=term --cov-fail-under=100 "$TARGET_DIR"
|
|
||||||
}
|
|
||||||
|
|
||||||
function download() {
|
function download() {
|
||||||
ANALYZERS=$1
|
ANALYZERS=$1
|
||||||
if [[ $ANALYZERS = "all" ]]; then
|
if [[ $ANALYZERS = "all" ]]; then
|
||||||
@@ -36,5 +19,5 @@ function download() {
|
|||||||
if [[ "$COMMAND" == "download" ]]; then
|
if [[ "$COMMAND" == "download" ]]; then
|
||||||
download "$2"
|
download "$2"
|
||||||
else
|
else
|
||||||
ci
|
../../../../pyci.sh $@
|
||||||
fi
|
fi
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user