Fix notification of individual services when related config changes, even when roles are grouped
This commit is contained in:
parent
08066595f1
commit
097022f782
8 changed files with 472 additions and 62 deletions
|
|
@ -38,3 +38,70 @@ def test_cm_module_uses_shared_state_io(tmp_path):
|
|||
assert CMModule.state_path(tmp_path) == written
|
||||
assert CMModule.load_state(tmp_path) == state
|
||||
assert CMModule._load_state(tmp_path) == state
|
||||
|
||||
|
||||
def test_active_service_units_for_package_snapshot_is_conservative():
|
||||
entries = [
|
||||
{
|
||||
"kind": "service",
|
||||
"snapshot": {
|
||||
"unit": "docker.service",
|
||||
"role_name": "docker",
|
||||
"packages": ["docker.io"],
|
||||
"active_state": "active",
|
||||
},
|
||||
},
|
||||
{
|
||||
"kind": "service",
|
||||
"snapshot": {
|
||||
"unit": "docker-cleanup.service",
|
||||
"role_name": "docker_cleanup",
|
||||
"packages": ["docker.io"],
|
||||
"active_state": "inactive",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
by_package = CMModule.active_service_units_by_package(entries)
|
||||
|
||||
assert by_package == {
|
||||
"docker.io": [{"unit": "docker.service", "role_name": "docker"}]
|
||||
}
|
||||
assert CMModule.active_service_units_for_package_snapshot(
|
||||
{"package": "docker.io", "role_name": "docker"}, by_package
|
||||
) == ["docker.service"]
|
||||
|
||||
|
||||
def test_active_service_units_for_package_snapshot_avoids_ambiguous_restarts():
|
||||
entries = [
|
||||
{
|
||||
"kind": "service",
|
||||
"snapshot": {
|
||||
"unit": "alpha.service",
|
||||
"role_name": "alpha",
|
||||
"packages": ["shared"],
|
||||
"active_state": "active",
|
||||
},
|
||||
},
|
||||
{
|
||||
"kind": "service",
|
||||
"snapshot": {
|
||||
"unit": "beta.service",
|
||||
"role_name": "beta",
|
||||
"packages": ["shared"],
|
||||
"active_state": "active",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
by_package = CMModule.active_service_units_by_package(entries)
|
||||
|
||||
assert (
|
||||
CMModule.active_service_units_for_package_snapshot(
|
||||
{"package": "shared", "role_name": "shared"}, by_package
|
||||
)
|
||||
== []
|
||||
)
|
||||
assert CMModule.active_service_units_for_package_snapshot(
|
||||
{"package": "shared", "role_name": "beta"}, by_package
|
||||
) == ["beta.service"]
|
||||
|
|
|
|||
|
|
@ -284,6 +284,12 @@ def test_manifest_writes_roles_and_playbook_with_clean_when(tmp_path: Path):
|
|||
assert "foo_systemd_enabled: true" in defaults
|
||||
assert "foo_systemd_state: stopped" in defaults
|
||||
|
||||
handlers = (out / "roles" / "foo" / "handlers" / "main.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "- name: Restart service" in handlers
|
||||
assert "state: restarted" in handlers
|
||||
|
||||
# Playbook should include users, etc_custom, packages, and services
|
||||
pb = (out / "playbook.yml").read_text(encoding="utf-8")
|
||||
assert "role: users" in pb
|
||||
|
|
@ -626,6 +632,154 @@ def test_manifest_groups_systemd_units_into_common_role(tmp_path: Path):
|
|||
tasks = (out / "roles" / "net" / "tasks" / "main.yml").read_text(encoding="utf-8")
|
||||
assert "Ensure grouped unit enablement matches harvest" in tasks
|
||||
assert 'no_log: "{{ enroll_hide_systemd_status | default(true) | bool }}"' in tasks
|
||||
assert "Restart managed services" not in tasks
|
||||
|
||||
defaults_text = (out / "roles" / "net" / "defaults" / "main.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "notify:" in defaults_text
|
||||
assert "- Restart managed service NetworkManager.service" in defaults_text
|
||||
assert (
|
||||
"Restart managed service NetworkManager-dispatcher.service" not in defaults_text
|
||||
)
|
||||
|
||||
handlers = (out / "roles" / "net" / "handlers" / "main.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "Run systemd daemon-reload" in handlers
|
||||
assert "- name: Restart managed service NetworkManager.service" in handlers
|
||||
assert "name: NetworkManager.service" in handlers
|
||||
assert "state: restarted" in handlers
|
||||
assert "Restart managed services" not in handlers
|
||||
assert "Restart managed service NetworkManager-dispatcher.service" not in handlers
|
||||
|
||||
|
||||
def test_manifest_common_package_file_notifies_matching_active_service(tmp_path: Path):
|
||||
bundle = tmp_path / "bundle"
|
||||
out = tmp_path / "ansible"
|
||||
(bundle / "artifacts" / "docker" / "etc" / "docker").mkdir(
|
||||
parents=True, exist_ok=True
|
||||
)
|
||||
(bundle / "artifacts" / "docker" / "etc" / "docker" / "daemon.json").write_text(
|
||||
'{"log-driver":"json-file"}\n', encoding="utf-8"
|
||||
)
|
||||
|
||||
state = {
|
||||
"schema_version": 3,
|
||||
"host": {"hostname": "test", "os": "debian", "pkg_backend": "dpkg"},
|
||||
"inventory": {
|
||||
"packages": {
|
||||
"docker.io": {
|
||||
"version": "1.0",
|
||||
"arches": ["amd64"],
|
||||
"installations": [
|
||||
{"version": "1.0", "arch": "amd64", "section": "admin"}
|
||||
],
|
||||
"section": "admin",
|
||||
"observed_via": [
|
||||
{"kind": "systemd_unit", "ref": "docker.service"},
|
||||
{"kind": "package_role", "ref": "docker"},
|
||||
],
|
||||
"roles": ["docker"],
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"users": {
|
||||
"role_name": "users",
|
||||
"users": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"unit": "docker.service",
|
||||
"role_name": "docker",
|
||||
"packages": ["docker.io"],
|
||||
"active_state": "active",
|
||||
"sub_state": "running",
|
||||
"unit_file_state": "enabled",
|
||||
"condition_result": "yes",
|
||||
"managed_files": [],
|
||||
"managed_dirs": [],
|
||||
"managed_links": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
}
|
||||
],
|
||||
"packages": [
|
||||
{
|
||||
"package": "docker.io",
|
||||
"role_name": "docker",
|
||||
"section": "admin",
|
||||
"has_config": True,
|
||||
"managed_files": [
|
||||
{
|
||||
"path": "/etc/docker/daemon.json",
|
||||
"src_rel": "etc/docker/daemon.json",
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"mode": "0644",
|
||||
"reason": "modified_conffile",
|
||||
}
|
||||
],
|
||||
"managed_dirs": [],
|
||||
"managed_links": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
}
|
||||
],
|
||||
"apt_config": {
|
||||
"role_name": "apt_config",
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"dnf_config": {
|
||||
"role_name": "dnf_config",
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"etc_custom": {
|
||||
"role_name": "etc_custom",
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"usr_local_custom": {
|
||||
"role_name": "usr_local_custom",
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"extra_paths": {
|
||||
"role_name": "extra_paths",
|
||||
"include_patterns": [],
|
||||
"exclude_patterns": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
},
|
||||
}
|
||||
_write_state(bundle, state)
|
||||
|
||||
manifest.manifest(str(bundle), str(out))
|
||||
|
||||
defaults = (out / "roles" / "admin" / "defaults" / "main.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "dest: /etc/docker/daemon.json" in defaults
|
||||
assert "- Restart managed service docker.service" in defaults
|
||||
|
||||
handlers = (out / "roles" / "admin" / "handlers" / "main.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "- name: Restart managed service docker.service" in handlers
|
||||
assert "name: docker.service" in handlers
|
||||
assert "Restart managed services" not in handlers
|
||||
|
||||
|
||||
def test_manifest_fqdn_implies_no_common_roles(tmp_path: Path):
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@ def test_manifest_puppet_writes_control_repo_style_output(tmp_path: Path):
|
|||
assert node_data["foo::files"]["/etc/foo/foo.conf"]["source"] == (
|
||||
"puppet:///modules/foo/nodes/test.example/etc/foo.conf"
|
||||
)
|
||||
assert node_data["foo::files"]["/etc/foo/foo.conf"]["notify"] == (
|
||||
"Service['foo.service']"
|
||||
)
|
||||
assert node_data["foo::services"]["foo.service"] == {
|
||||
"ensure": "running",
|
||||
"enable": True,
|
||||
|
|
@ -483,6 +486,7 @@ def test_manifest_puppet_uses_default_node_and_common_package_modules(tmp_path:
|
|||
assert "package { 'foo':" in net_pp
|
||||
assert "file { '/etc/foo/foo.conf':" in net_pp
|
||||
assert "source => 'puppet:///modules/net/etc/foo.conf'" in net_pp
|
||||
assert "notify => Service['foo.service']" in net_pp
|
||||
assert "service { 'foo.service':" in net_pp
|
||||
assert (out / "modules" / "net" / "files" / "etc" / "foo.conf").exists()
|
||||
assert not (out / "modules" / "curl").exists()
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ def test_manifest_salt_writes_single_site_state_tree(tmp_path: Path):
|
|||
assert '- name: "foo"' in net_sls
|
||||
assert '"/etc/foo/foo.conf":' in net_sls
|
||||
assert 'source: "salt://roles/net/files/etc/foo.conf"' in net_sls
|
||||
assert "watch_in:" in net_sls
|
||||
assert 'service: "enroll_service_net_foo_service_20435514"' in net_sls
|
||||
assert "file.symlink:" in net_sls
|
||||
assert "service.running:" in net_sls
|
||||
assert (out / "states" / "roles" / "net" / "files" / "etc" / "foo.conf").exists()
|
||||
|
|
@ -531,6 +533,9 @@ def test_manifest_salt_uses_jinjaturtle_templates(monkeypatch, tmp_path: Path):
|
|||
pillar = yaml.safe_load(pillar_path.with_suffix(".sls").read_text(encoding="utf-8"))
|
||||
file_data = pillar["enroll"]["roles"]["foo"]["files"]["/etc/foo/foo.conf"]
|
||||
assert file_data["source"] == "salt://roles/foo/templates/etc/foo.conf.j2"
|
||||
assert file_data["watch_in"] == [
|
||||
{"service": "enroll_service_foo_foo_service_20435514"}
|
||||
]
|
||||
assert file_data["template"] == "jinja"
|
||||
assert file_data["context"] == {"foo_setting": True}
|
||||
|
||||
|
|
|
|||
Reference in a new issue