Skip to content

Commit

Permalink
Provide a dict to _JujuContext directly.
Browse files Browse the repository at this point in the history
No point manipulating os.environ - just provide the expected environment as a dictionary to the _JujuContext object.
  • Loading branch information
tonyandrewmeyer committed Nov 19, 2024
1 parent d0ad8ee commit 786aead
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 21 deletions.
16 changes: 10 additions & 6 deletions testing/src/scenario/ops_main_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,16 @@ def setup_framework(
):
from .mocking import _MockModelBackend

if juju_context is None:
juju_context = ops.jujucontext._JujuContext.from_dict(os.environ)
model_backend = _MockModelBackend(
state=state,
event=event,
context=context,
charm_spec=charm_spec,
juju_context=ops.jujucontext._JujuContext.from_dict(os.environ)
if juju_context is None
else juju_context,
juju_context=juju_context,
)
debug = "JUJU_DEBUG" in os.environ
setup_root_logging(model_backend, debug=debug)
setup_root_logging(model_backend, debug=juju_context.debug)
# ops sets sys.excepthook to go to Juju's debug-log, but that's not useful
# in a testing context, so reset it.
sys.excepthook = sys.__excepthook__
Expand Down Expand Up @@ -190,12 +189,17 @@ def __init__(
event: "_Event",
context: "Context",
charm_spec: "_CharmSpec[CharmType]",
juju_context: Optional[ops.jujucontext._JujuContext] = None,
):
self.state = state
self.event = event
self.context = context
self.charm_spec = charm_spec
self.juju_context = ops.jujucontext._JujuContext.from_dict(os.environ)
self.juju_context = (
ops.jujucontext._JujuContext.from_dict(os.environ)
if juju_context is None
else juju_context
)

# set by setup()
self.dispatcher: Optional[_Dispatcher] = None
Expand Down
19 changes: 4 additions & 15 deletions testing/src/scenario/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import copy
import dataclasses
import marshal
import os
import re
import tempfile
import typing
Expand Down Expand Up @@ -35,6 +34,7 @@
NoTypeError,
PreCommitEvent,
)
from ops.jujucontext import _JujuContext
from ops.storage import NoSnapshotError, SQLiteStorage
from ops.framework import _event_regex
from ops._private.harness import ActionFailed
Expand Down Expand Up @@ -183,15 +183,6 @@ def __init__(
self._app_name = app_name
self._unit_id = unit_id

@staticmethod
def _cleanup_env(env: Dict[str, str]):
# TODO consider cleaning up env on __delete__, but ideally you should be
# running this in a clean env or a container anyway.
# cleanup the env, in case we'll be firing multiple events, we don't want to pollute it.
for key in env:
# os.unsetenv does not always seem to work !?
del os.environ[key]

def _get_event_env(self, state: "State", event: "_Event", charm_root: Path):
"""Build the simulated environment the operator framework expects."""
env = {
Expand Down Expand Up @@ -430,7 +421,7 @@ def exec(
Returns the 'output state', that is, the state as mutated by the charm during the
event handling.
This will set the environment up and call ops.main.main().
This will set the environment up and call ops.main().
After that it's up to ops.
"""
# todo consider forking out a real subprocess and do the mocking by
Expand All @@ -457,7 +448,7 @@ def exec(
event=event,
charm_root=temporary_charm_root,
)
os.environ.update(env)
juju_context = _JujuContext.from_dict(env)

logger.info(" - Entering ops.main (mocked).")
from .ops_main_mock import Ops # noqa: F811
Expand All @@ -471,6 +462,7 @@ def exec(
self._charm_spec,
charm_type=self._wrap(charm_type),
),
juju_context=juju_context,
)
ops.setup()

Expand All @@ -489,9 +481,6 @@ def exec(
finally:
logger.info(" - Exited ops.main.")

logger.info(" - Clearing env")
self._cleanup_env(env)

logger.info(" - closing storage")
output_state = self._close_storage(output_state, temporary_charm_root)

Expand Down

0 comments on commit 786aead

Please sign in to comment.