mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
first working performance test
This commit is contained in:
parent
07e217d516
commit
dc3a1bd012
2 changed files with 226 additions and 72 deletions
|
@ -97,20 +97,52 @@ def state_tree(integration_files_dir):
|
|||
"""
|
||||
dirname = integration_files_dir / "state-tree"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
(dirname / "testfile").write_text("This is a test file")
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def pillar_tree(integration_files_dir):
|
||||
def sls_contents():
|
||||
return """
|
||||
add_file:
|
||||
file.managed:
|
||||
- name: {path}
|
||||
- source: salt://testfile
|
||||
- makedirs: true
|
||||
- require:
|
||||
- cmd: echo
|
||||
delete_file:
|
||||
file.absent:
|
||||
- name: {path}
|
||||
- require:
|
||||
- file: add_file
|
||||
echo:
|
||||
cmd.run:
|
||||
- name: \"echo 'This is a test!'\"
|
||||
"""
|
||||
Fixture which returns the salt pillar tree root directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = integration_files_dir / "pillar-tree"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def salt_cli(salt_master):
|
||||
return salt_master.salt_cli()
|
||||
@pytest.fixture(scope="package")
|
||||
def file_add_delete_sls(testfile_path, state_tree):
|
||||
sls_name = "file_add"
|
||||
sls_contents = """
|
||||
add_file:
|
||||
file.managed:
|
||||
- name: {path}
|
||||
- source: salt://testfile
|
||||
- makedirs: true
|
||||
- require:
|
||||
- cmd: echo
|
||||
delete_file:
|
||||
file.absent:
|
||||
- name: {path}
|
||||
- require:
|
||||
- file: add_file
|
||||
echo:
|
||||
cmd.run:
|
||||
- name: \"echo 'This is a test!'\"
|
||||
""".format(
|
||||
path=testfile_path
|
||||
)
|
||||
with pytest.helpers.temp_file("{}.sls".format(sls_name), sls_contents, state_tree):
|
||||
yield sls_name
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
@ -6,6 +8,10 @@ from saltfactories.daemons import master
|
|||
from saltfactories.daemons.container import SaltDaemon, SaltMinion
|
||||
from saltfactories.utils import random_string
|
||||
|
||||
from salt.version import SaltVersionsInfo
|
||||
|
||||
pytestmark = [pytest.mark.skip_if_binaries_missing("docker")]
|
||||
|
||||
|
||||
class ContainerMaster(SaltDaemon, master.SaltMaster):
|
||||
"""
|
||||
|
@ -28,16 +34,17 @@ class ContainerMinion(SaltMinion):
|
|||
return []
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def compat_salt_version():
|
||||
return "3004"
|
||||
# ---------------------- Docker Setup ----------------------
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def master_id(compat_salt_version):
|
||||
return random_string(
|
||||
"master-performance-{}-".format(compat_salt_version), uppercase=False
|
||||
)
|
||||
@pytest.fixture(scope="package")
|
||||
def prev_version():
|
||||
return str(SaltVersionsInfo.previous_release().info[0])
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def container_master_id(prev_version):
|
||||
return random_string("master-performance-{}-".format(prev_version), uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
|
@ -46,13 +53,11 @@ def container_master(
|
|||
salt_factories,
|
||||
host_docker_network_ip_address,
|
||||
network,
|
||||
state_tree,
|
||||
pillar_tree,
|
||||
compat_salt_version,
|
||||
prev_version,
|
||||
docker_client,
|
||||
master_id,
|
||||
container_master_id,
|
||||
):
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(master_id)
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(container_master_id)
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(exist_ok=True)
|
||||
|
||||
|
@ -73,31 +78,19 @@ def container_master(
|
|||
},
|
||||
}
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"file_roots": {"base": [str(state_tree)]},
|
||||
"pillar_roots": {"base": [str(pillar_tree)]},
|
||||
}
|
||||
)
|
||||
factory = salt_factories.salt_master_daemon(
|
||||
master_id,
|
||||
container_master_id,
|
||||
defaults=config_defaults,
|
||||
overrides=config_overrides,
|
||||
factory_class=ContainerMaster,
|
||||
image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(
|
||||
compat_salt_version
|
||||
),
|
||||
image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(prev_version),
|
||||
base_script_args=["--log-level=debug"],
|
||||
container_run_kwargs={
|
||||
# "ports": {
|
||||
# f"{publish_port}/tcp": publish_port,
|
||||
# f"{ret_port}/tcp": ret_port,
|
||||
# },
|
||||
"network": network,
|
||||
"hostname": master_id,
|
||||
"hostname": container_master_id,
|
||||
},
|
||||
docker_client=docker_client,
|
||||
name=master_id,
|
||||
name=container_master_id,
|
||||
start_timeout=120,
|
||||
max_start_attempts=1,
|
||||
skip_if_docker_client_not_connectable=True,
|
||||
|
@ -106,61 +99,58 @@ def container_master(
|
|||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def salt_cli(container_master):
|
||||
@pytest.fixture(scope="package")
|
||||
def container_salt_cli(container_master):
|
||||
return container_master.salt_cli()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def salt_key_cli(container_master):
|
||||
@pytest.fixture(scope="package")
|
||||
def container_salt_key_cli(container_master):
|
||||
return container_master.salt_key_cli()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def salt_run_cli(container_master):
|
||||
@pytest.fixture(scope="package")
|
||||
def container_salt_run_cli(container_master):
|
||||
return container_master.salt_run_cli()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def minion_id(compat_salt_version):
|
||||
@pytest.fixture(scope="package")
|
||||
def container_minion_id(prev_version):
|
||||
return random_string(
|
||||
"minion-performance-{}-".format(compat_salt_version),
|
||||
"minion-performance-{}-".format(prev_version),
|
||||
uppercase=False,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_if_binaries_missing("docker")
|
||||
@pytest.fixture()
|
||||
@pytest.fixture(scope="package")
|
||||
def container_minion(
|
||||
minion_id,
|
||||
container_minion_id,
|
||||
container_master,
|
||||
docker_client,
|
||||
compat_salt_version,
|
||||
prev_version,
|
||||
host_docker_network_ip_address,
|
||||
network,
|
||||
master_id,
|
||||
container_master_id,
|
||||
):
|
||||
config_overrides = {
|
||||
"master": master_id,
|
||||
"master": container_master_id,
|
||||
"user": False,
|
||||
"pytest-minion": {"log": {"host": host_docker_network_ip_address}},
|
||||
}
|
||||
factory = container_master.salt_minion_daemon(
|
||||
minion_id,
|
||||
container_minion_id,
|
||||
overrides=config_overrides,
|
||||
factory_class=ContainerMinion,
|
||||
# SaltMinion kwargs
|
||||
name=minion_id,
|
||||
image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(
|
||||
compat_salt_version
|
||||
),
|
||||
name=container_minion_id,
|
||||
image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(prev_version),
|
||||
docker_client=docker_client,
|
||||
start_timeout=120,
|
||||
pull_before_start=False,
|
||||
skip_if_docker_client_not_connectable=True,
|
||||
container_run_kwargs={
|
||||
"network": network,
|
||||
"hostname": minion_id,
|
||||
"hostname": container_minion_id,
|
||||
},
|
||||
max_start_attempts=1,
|
||||
)
|
||||
|
@ -171,6 +161,103 @@ def container_minion(
|
|||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def container_sls(sls_contents, state_tree, tmp_path):
|
||||
sls_name = "container"
|
||||
location = tmp_path / "container" / "testfile"
|
||||
location.parent.mkdir()
|
||||
with pytest.helpers.temp_file(
|
||||
"{}.sls".format(sls_name), sls_contents.format(path=str(location)), state_tree
|
||||
):
|
||||
yield sls_name
|
||||
|
||||
|
||||
# ---------------------- Local Setup ----------------------
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def master_id():
|
||||
return random_string("master-performance-", uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_master(
|
||||
request,
|
||||
salt_factories,
|
||||
master_id,
|
||||
):
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(master_id)
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(exist_ok=True)
|
||||
|
||||
config_defaults = {
|
||||
"root_dir": str(root_dir),
|
||||
"transport": request.config.getoption("--transport"),
|
||||
"user": False,
|
||||
}
|
||||
publish_port = ports.get_unused_localhost_port()
|
||||
ret_port = ports.get_unused_localhost_port()
|
||||
config_overrides = {
|
||||
"interface": "127.0.0.1",
|
||||
"publish_port": publish_port,
|
||||
"ret_port": ret_port,
|
||||
"log_level_logfile": "quiet",
|
||||
}
|
||||
|
||||
factory = salt_factories.salt_master_daemon(
|
||||
master_id,
|
||||
defaults=config_defaults,
|
||||
overrides=config_overrides,
|
||||
start_timeout=120,
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_cli(salt_master):
|
||||
return salt_master.salt_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def minion_id():
|
||||
return random_string(
|
||||
"minion-performance-",
|
||||
uppercase=False,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_minion(
|
||||
minion_id,
|
||||
salt_master,
|
||||
):
|
||||
config_overrides = {
|
||||
"user": False,
|
||||
}
|
||||
factory = salt_master.salt_minion_daemon(
|
||||
minion_id,
|
||||
overrides=config_overrides,
|
||||
start_timeout=120,
|
||||
)
|
||||
factory.after_terminate(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master, factory.id
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_sls(sls_contents, state_tree, tmp_path):
|
||||
sls_name = "local"
|
||||
location = tmp_path / "local" / "testfile"
|
||||
location.parent.mkdir()
|
||||
with pytest.helpers.temp_file(
|
||||
"{}.sls".format(sls_name), sls_contents.format(path=str(location)), state_tree
|
||||
):
|
||||
yield sls_name
|
||||
|
||||
|
||||
def _wait_for_stdout(expected, func, *args, timeout=120, **kwargs):
|
||||
start = time.time()
|
||||
while time.time() < start + timeout:
|
||||
|
@ -183,26 +270,61 @@ def _wait_for_stdout(expected, func, *args, timeout=120, **kwargs):
|
|||
|
||||
|
||||
def test_performance(
|
||||
salt_cli,
|
||||
container_salt_cli,
|
||||
container_minion,
|
||||
salt_run_cli,
|
||||
salt_key_cli,
|
||||
compat_salt_version,
|
||||
container_salt_run_cli,
|
||||
container_salt_key_cli,
|
||||
prev_version,
|
||||
container_master,
|
||||
state_tree,
|
||||
salt_cli,
|
||||
salt_minion,
|
||||
salt_master,
|
||||
container_sls,
|
||||
local_sls,
|
||||
):
|
||||
# Copy all of the needed files to both master file roots directories
|
||||
shutil.copytree(
|
||||
state_tree, salt_master.config["file_roots"]["base"][0], dirs_exist_ok=True
|
||||
)
|
||||
shutil.copytree(
|
||||
state_tree, container_master.config["file_roots"]["base"][0], dirs_exist_ok=True
|
||||
)
|
||||
|
||||
# Wait for the container master and minion to start
|
||||
_wait_for_stdout(
|
||||
compat_salt_version,
|
||||
container_master.run,
|
||||
*salt_run_cli.cmdline("--versions-report")
|
||||
prev_version, container_master.run, *container_salt_run_cli.cmdline("--version")
|
||||
)
|
||||
salt_key_cmd = [
|
||||
comp
|
||||
for comp in salt_key_cli.cmdline("-Ay")
|
||||
for comp in container_salt_key_cli.cmdline("-Ay")
|
||||
if not comp.startswith("--log-level")
|
||||
]
|
||||
_wait_for_stdout(container_minion.id, container_master.run, *salt_key_cmd)
|
||||
|
||||
versions_ret = container_master.run(
|
||||
*salt_cli.cmdline("test.versions", minion_tgt=container_minion.id)
|
||||
_wait_for_stdout(
|
||||
"Salt: {}".format(prev_version),
|
||||
container_master.run,
|
||||
*container_salt_cli.cmdline("test.versions", minion_tgt=container_minion.id)
|
||||
)
|
||||
assert compat_salt_version in versions_ret.stdout
|
||||
|
||||
# Let's now apply the states
|
||||
applies = os.environ.get("SALT_PERFORMANCE_TEST_APPLIES", 3)
|
||||
container_salt_cmd = container_salt_cli.cmdline(
|
||||
"state.apply", container_sls, minion_tgt=container_minion.id
|
||||
)
|
||||
|
||||
start = time.time()
|
||||
for _ in range(applies):
|
||||
container_state_ret = container_master.run(*container_salt_cmd)
|
||||
assert container_state_ret.data
|
||||
container_duration = time.time() - start
|
||||
|
||||
start = time.time()
|
||||
for _ in range(applies):
|
||||
local_state_ret = salt_cli.run(
|
||||
"state.apply", local_sls, minion_tgt=salt_minion.id
|
||||
)
|
||||
assert local_state_ret.data
|
||||
local_duration = time.time() - start
|
||||
|
||||
assert local_duration <= 1.01 * container_duration
|
||||
|
|
Loading…
Add table
Reference in a new issue