charmed-kubernetes / pytest-operator

Apache License 2.0
6 stars 13 forks source link

MAAS cloud model name issue when using build_charm method #123

Open dashmage opened 4 months ago

dashmage commented 4 months ago

While running tests on a MAAS juju cloud where the model is named admin/mymodel according to the <user>/<model> convention, the ops_test.build_charm method doesn't work


Steps to reproduce error

Happens when a test uses ops_test.build_charm("."). Traceback logs are provided below.

    @pytest.mark.abort_on_fail
    @pytest.mark.skip_if_deployed
    async def test_build_and_deploy(ops_test: OpsTest, series, sync_helper, provided_collectors, resources):
        """Build the charm-under-test and deploy it together with related charms.

        Assert on the unit status before any relations/configurations take place.
        """
        # Build and deploy charm from local source folder
>       charm = await ops_test.build_charm(".")

tests/functional/test_charm.py:70:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.tox/func31/lib/python3.11/site-packages/pytest_operator/plugin.py:943: in build_charm
    charms_dst_dir = self.tmp_path / "charms"
.tox/func31/lib/python3.11/site-packages/pytest_operator/plugin.py:518: in tmp_path
    tmp_path = self._tmp_path_factory.mktemp(current_state.model_name)
.tox/func31/lib/python3.11/site-packages/_pytest/tmpdir.py:131: in mktemp
    basename = self._ensure_relative_to_basetemp(basename)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x75b39e836d10>, _basetemp=PosixPath('/tmp/pytest-of-dashmage/pytest-0'), _retention_count=3, _retention_policy='all')
basename = 'admin/mymodel'

    def _ensure_relative_to_basetemp(self, basename: str) -> str:
        basename = os.path.normpath(basename)
        if (self.getbasetemp() / basename).resolve().parent != self.getbasetemp():
>           raise ValueError(f"{basename} is not a normalized and relative path")
E           ValueError: admin/mymodel is not a normalized and relative path

Analysis

From the logs, it looks like pytest-operator isn't able to create a new tmp directory due to the presence of the "/" in the model name.

Temporary workaround

Made changes here. Not sure if this might break things elsewhere since the name of the tmp directory is being changed.

def tmp_path(self) -> Path:
    (...)
    if current_state and current_state.tmp_path is None:
        model_name = current_state.model_name
        if "/" in current_state.model_name:
            model_name = "-".join(model_name.split("/"))
            tmp_path = self._tmp_path_factory.mktemp(model_name)
    (...)