Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(beaker): suppress 10_avc_check restraint plugin #290

Merged
merged 2 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/mrack/providers/beaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ def _req_to_bkr_job(self, req): # pylint: disable=too-many-locals
recipe.addReservesys(duration=str(self.reserve_duration))

for task in specs["tasks"]:
recipe.addTask(task=task["name"], role=task["role"])
recipe.addTask(
task=task["name"],
role=task["role"],
taskParams=task.get("params"),
)

# Create RecipeSet and add our Recipe to it.
recipe_set = BeakerRecipeSet(**specs)
Expand Down
8 changes: 7 additions & 1 deletion src/mrack/transformers/beaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,13 @@ def create_host_requirement(self, host):
"tasks",
host["os"],
default=[ # we use dummy task because beaker require a task in recipe
{"name": "/distribution/dummy", "role": "STANDALONE"}
{
"name": "/distribution/dummy",
"role": "STANDALONE",
"params": [
"RSTRNT_DISABLED=10_avc_check",
],
}
],
),
"ks_append": self._construct_ks_append_script(
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import shutil
import socket
import tempfile
from pathlib import Path

Expand Down Expand Up @@ -45,3 +46,20 @@ def cleandir():
yield
os.chdir(old_cwd)
shutil.rmtree(newpath)


@pytest.fixture
def mock_gethostbyaddr(monkeypatch):
"""
Mock gethostbyaddr function from socket module.

It returns only IP address as if the DNS resolution would fail - which it does
for test data anyway.

This is to speed up the tests
"""

def gethostbyaddr(ip_address):
return [ip_address, [], []]

monkeypatch.setattr(socket, "gethostbyaddr", gethostbyaddr)
8 changes: 7 additions & 1 deletion tests/integration/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ def global_context_init(provisioning_config_file, mrack_config_file=None, db_fil
class TestStaticProvider:
@pytest.mark.asyncio
async def test_up_action(
self, provisioning_config, metadata, database, setup_providers
self,
provisioning_config,
metadata,
database,
setup_providers,
mock_gethostbyaddr,
):
up_action = UpAction(
config=provisioning_config,
Expand Down Expand Up @@ -88,6 +93,7 @@ async def test_output_action(
cleandir,
config,
files,
mock_gethostbyaddr,
):
workdir = os.getcwd()

Expand Down
18 changes: 18 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import socket
from unittest.mock import MagicMock, PropertyMock

import pytest
Expand Down Expand Up @@ -185,3 +186,20 @@ def host1_osp(metahost1):
@pytest.fixture
def host_win_aws(metahost_win):
return meta_to_host(metahost_win, "aws", "3", "192.168.0.129")


@pytest.fixture
def mock_gethostbyaddr(monkeypatch):
"""
Mock gethostbyaddr function from socket module.

It returns only IP address as if the DNS resolution would fail - which it does
for test data anyway.

This is to speed up the tests
"""

def gethostbyaddr(ip_address):
return [ip_address, [], []]

monkeypatch.setattr(socket, "gethostbyaddr", gethostbyaddr)
36 changes: 17 additions & 19 deletions tests/unit/test_ansible_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class TestAnsibleInventory:
False,
],
)
def test_layouts(self, layout, db, metadata):
def test_layouts(self, layout, db, metadata, mock_gethostbyaddr):
config = provisioning_config(layout)
ans_inv = AnsibleInventoryOutput(config, db, metadata)
inventory = ans_inv.create_inventory()
Expand All @@ -123,15 +123,15 @@ def test_layouts(self, layout, db, metadata):
(True, False),
],
)
def test_invalid_layouts(self, layout, db, metadata):
def test_invalid_layouts(self, layout, db, metadata, mock_gethostbyaddr):
config = provisioning_config(layout)
ans_inv = AnsibleInventoryOutput(config, db, metadata)

with pytest.raises(ConfigError) as excinfo:
ans_inv.create_inventory()
assert "dictionary" in str(excinfo.value)

def test_layout_nested_groups(self, db, metadata):
def test_layout_nested_groups(self, db, metadata, mock_gethostbyaddr):
layout = {
"all": {
"children": {
Expand All @@ -145,10 +145,6 @@ def test_layout_nested_groups(self, db, metadata):
ans_inv = AnsibleInventoryOutput(config, db, metadata)
inventory = ans_inv.create_inventory()

import yaml

print(yaml.dump(inventory))

assert "all" in inventory
assert "children" in inventory["all"]

Expand Down Expand Up @@ -176,7 +172,7 @@ def test_layout_nested_groups(self, db, metadata):
in inventory["all"]["children"]["server"]["children"]["ipaserver"]["hosts"]
)

def test_layout_overwrite(self, db, metadata):
def test_layout_overwrite(self, db, metadata, mock_gethostbyaddr):
metadata["config"] = {
"ansible": {
"layout": {
Expand All @@ -198,7 +194,7 @@ def test_layout_overwrite(self, db, metadata):
assert "windows" not in inventory["all"]["children"]
assert "mylayout" in inventory["all"]["children"]

def test_meta_extra(self, db_meta_extra, metadata):
def test_meta_extra(self, db_meta_extra, metadata, mock_gethostbyaddr):
config = provisioning_config()
ans_inv = AnsibleInventoryOutput(config, db_meta_extra, metadata)
inventory = ans_inv.create_inventory()
Expand All @@ -211,7 +207,7 @@ def test_meta_extra(self, db_meta_extra, metadata):
), "Host must have 'meta_compose_url' field"
assert "meta_compose_id" in first_host, "Host must have 'meta_compose_id' field"

def test_not_meta_extra(self, db, metadata):
def test_not_meta_extra(self, db, metadata, mock_gethostbyaddr):
"""
Because some images (such as Windows images) don't have extra meta data fields
like meta_compose_id and meta_compose_url, inventory shouldn't output them
Expand All @@ -232,7 +228,7 @@ def test_not_meta_extra(self, db, metadata):
"meta_compose_id" not in first_host
), "Host must NOT have 'meta_compose_id' field"

def test_arbitrary_meta_attrs(self):
def test_arbitrary_meta_attrs(self, mock_gethostbyaddr):
"""
Test that inventory has meta_$something attribute if user defined it in job
metadata file. Also test that they override the default meta attrs, e.g.,
Expand All @@ -259,7 +255,7 @@ def test_arbitrary_meta_attrs(self):
assert srv2["meta_readonly_dc"] == "no"
assert srv2["meta_os"] == "fedora-32"

def test_arbitrary_attrs(self):
def test_arbitrary_attrs(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in host part
of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -296,7 +292,7 @@ def test_arbitrary_attrs(self):
assert srv2["no_ca"] == "yes"
assert srv2["something_else"] == "for_fun"

def test_domain_arbitrary_attrs(self):
def test_domain_arbitrary_attrs(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in domain
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -327,7 +323,7 @@ def test_domain_arbitrary_attrs(self):
assert srv2["no_ca"] == "no"
assert srv2["something_else"] == "not_funny"

def test_domain_arbitrary_attrs_override(self):
def test_domain_arbitrary_attrs_override(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in domain
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -368,7 +364,7 @@ def test_domain_arbitrary_attrs_override(self):
assert srv2["no_ca"] == "yes"
assert srv2["something_else"] == "for_fun"

def test_global_arbitrary_attrs(self):
def test_global_arbitrary_attrs(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in global
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -399,7 +395,7 @@ def test_global_arbitrary_attrs(self):
assert srv2["no_ca"] == "no"
assert srv2["something_else"] == "not_funny"

def test_global_arbitrary_attrs_domain_override(self):
def test_global_arbitrary_attrs_domain_override(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in global
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -434,7 +430,7 @@ def test_global_arbitrary_attrs_domain_override(self):
assert srv2["no_ca"] == "yes"
assert srv2["something_else"] == "not_funny"

def test_global_arbitrary_attrs_host_override(self):
def test_global_arbitrary_attrs_host_override(self, mock_gethostbyaddr):
"""
Test that values defined in `ansible_inventory` dictionary in global
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -481,7 +477,9 @@ def test_global_arbitrary_attrs_host_override(self):
assert srv2["no_ca"] == "whatever"
assert srv2["something_else"] == "host_value"

def test_global_arbitrary_attrs_host_override_multiple_domains(self):
def test_global_arbitrary_attrs_host_override_multiple_domains(
self, mock_gethostbyaddr
):
"""
Test that values defined in `ansible_inventory` dictionary in global
section of job metadata file gets into host attributes in generated ansible
Expand Down Expand Up @@ -547,7 +545,7 @@ def test_global_arbitrary_attrs_host_override_multiple_domains(self):
assert d1_srv2["no_ca"] == "no"
assert d1_srv2["something_else"] == "default_global"

def test_host_ssh_options(self, metadata, db):
def test_host_ssh_options(self, metadata, db, mock_gethostbyaddr):
prov_config = provisioning_config()
ans_inv = AnsibleInventoryOutput(prov_config, db, metadata)

Expand Down
38 changes: 35 additions & 3 deletions tests/unit/test_beaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@

import pytest

from mrack.providers import providers
from mrack.providers.beaker import BeakerProvider

from .mock_data import MockedBeakerTransformer, provisioning_config
from .utils import get_content, get_file_path


@pytest.fixture
def mock_beaker_conf(monkeypatch):
monkeypatch.setenv("BEAKER_CONF", get_file_path("client.conf"))


class TestBeakerProvider:
def setup_method(self):

self.mock_hub = Mock()
self.result_xml = get_content("result.xml")
self.mock_hub.taskactions.to_xml = Mock(return_value=self.result_xml)
Expand All @@ -45,8 +51,7 @@ def teardown_method(self):
mock.patch.stopall()

@pytest.mark.asyncio
async def test_get_repo_info(self, monkeypatch):
monkeypatch.setenv("BEAKER_CONF", get_file_path("client.conf"))
async def test_get_repo_info(self, mock_beaker_conf):
provider = BeakerProvider()
await provider.init(self.distros, self.timeout, self.reserve_duration)
bkr_res = provider._get_recipe_info(self.beaker_id, self.log_msg_start)
Expand All @@ -59,3 +64,30 @@ async def test_get_repo_info(self, monkeypatch):
"console.log": "https://test.example.com/logs/console.log",
"anaconda.log": "https://test.example.com/logs/anaconda.log",
}

@pytest.mark.asyncio
async def test_beaker_job_creation(self, mock_beaker_conf):
# Given initialized beaker provider and transformer with real beaker
# calls mocked
providers.register("beaker", BeakerProvider)
provider = providers.get("beaker")
await provider.init(self.distros, self.timeout, self.reserve_duration)
bkr_transformer = MockedBeakerTransformer()

await bkr_transformer.init(provisioning_config(), {})
bkr_transformer.add_host(
{
"name": "host.example.test",
"group": "client",
"os": "Fedora-31%",
}
)

# When having a host requirement and creating a Beaker job
req = bkr_transformer.create_host_requirements()[0]
job = provider._req_to_bkr_job(req)

# Then the job contains param to supress 10_avc_check restraint plugin
# so that provisioning won't fail on AVC denials
xml = job.toxml()
assert '<param name="RSTRNT_DISABLED" value="10_avc_check"/>' in xml
10 changes: 9 additions & 1 deletion tests/unit/test_beaker_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ class TestBeakerTransformer:
cat_release = "cat /etc/redhat-release"
wget = "wget redhat.com"
default_whiteboard = "This job has been created using mrack."
default_tasks = [{"name": "/distribution/dummy", "role": "STANDALONE"}]
default_tasks = [
{
"name": "/distribution/dummy",
"role": "STANDALONE",
"params": [
"RSTRNT_DISABLED=10_avc_check",
],
}
]
default_retention_tag = "audit"
default_product = "[internal]"

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_pytest_mh.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def mock_metadata():


class TestPytestMhOutput:
def test_output(self, mock_metadata):
def test_output(self, mock_metadata, mock_gethostbyaddr):
config = provisioning_config()
db = get_db_from_metadata(mock_metadata)

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_pytest_multihost.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class TestPytestMultihostOutput:
def test_arbitrary_attrs(self):
def test_arbitrary_attrs(self, mock_gethostbyaddr):
"""
Test that values defined in `pytest_multihost` dictionary in host part
of job metadata file gets into host attributes in generated pytest-multihost
Expand Down Expand Up @@ -40,7 +40,7 @@ def test_arbitrary_attrs(self):
assert srv2["no_ca"] == "yes"
assert srv2["something_else"] == "for_fun"

def test_config_section_deleted(self):
def test_config_section_deleted(self, mock_gethostbyaddr):
"""
Test that config section from metadata is not included in mhc.yaml.
"""
Expand Down
Loading