Skip to content

jhack explode when no slot connected and no .config folder exist #224

@taurus-forever

Description

@taurus-forever

Bug Description

I have started new LXC VM: lxc launch --vm ubuntu:24.04 2xenrico
and installed Canonical K8s + Juju + jhack there to fire an event (freshly installed no snap slots connected, no /root/.config/jhack folder, etc). Jhack explode into my face (see below) on jhack fire postgresql-k8s/0 update-status.

To Reproduce

See above in the bug description.

Environment

root@2xenrico:~# snap list
Name     Version        Rev    Tracking             Publisher   Notes
core20   20250526       2599   latest/stable        canonical✓  base
core24   20250504       988    latest/stable        canonical✓  base
jhack    0.4.4.0.20.27  547    latest/edge          ppasotti    -
juju     3.6.7          31266  3/stable             canonical✓  -
k8s      v1.32.5        3581   1.32-classic/stable  canonical✓  classic
kubectl  1.32.5         3593   latest/stable        canonical✓  classic
snapd    2.68.4         24505  latest/stable        canonical✓  snapd
root@2xenrico:~# 

Relevant log output

root@2xenrico:~# jhack fire postgresql-k8s/0 update-status
ERROR:jhack:It seems like the snap doesn't have access to /root/.local/share/juju;to grant it, run 'sudo snap connect jhack:dot-local-share-juju snapd'.Some Jhack commands will still work, but those that interact with the juju client will not.
--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib/python3.12/pathlib.py", line 1313, in mkdir
    os.mkdir(self, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/root/.config/jhack'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/conf/conf.py", line 48, in _get_config_path
    jconf.parent.mkdir(parents=True, exist_ok=True)
  File "/usr/lib/python3.12/pathlib.py", line 1317, in mkdir
    self.parent.mkdir(parents=True, exist_ok=True)
  File "/usr/lib/python3.12/pathlib.py", line 1313, in mkdir
    os.mkdir(self, mode)
PermissionError: [Errno 13] Permission denied: '/root/.config'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.12/logging/__init__.py", line 1160, in emit
    msg = self.format(record)
          ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/logging/__init__.py", line 999, in format
    return fmt.format(record)
           ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/logging/__init__.py", line 703, in format
    record.message = record.getMessage()
                     ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/logging/__init__.py", line 392, in getMessage
    msg = msg % self.args
          ~~~~^~~~~~~~~~~
TypeError: not all arguments converted during string formatting
Call stack:
  File "/snap/jhack/547/bin/jhack", line 8, in <module>
    sys.exit(main())
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/main.py", line 25, in main
    from jhack.chaos.flicker import flicker
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/chaos/flicker.py", line 9, in <module>
    from jhack.conf.conf import check_destructive_commands_allowed
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/conf/conf.py", line 225, in <module>
    CONFIG = Config()
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/conf/conf.py", line 26, in __init__
    path, is_default = self._get_config_path()
  File "/snap/jhack/547/lib/python3.12/site-packages/jhack/conf/conf.py", line 54, in _get_config_path
    logger.exception(
Message: 'Error encountered while attempting to initialize user config: '
Arguments: ("Failed to create default user config in /root/.config/jhack/config.toml. You'll have to do that manually.",)
╭───────────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:565 in simulate_event                                                                                                                                                     │
│                                                                                                                                                                                                                                                      │
│   562 │                                                                                        ╭─────────────── locals ───────────────╮                                                                                                              │
│   563 │   Especially useful in combination with jhack charm sync and/or debug-code/debug-hooks │      check_name = None               │                                                                                                              │
│   564 │   """                                                                                  │         dry_run = None               │                                                                                                              │
│ ❱ 565 │   return _simulate_event(                                                              │    env_override = None               │                                                                                                              │
│   566 │   │   target,                                                                          │           event = 'update-status'    │                                                                                                              │
│   567 │   │   event,                                                                           │           model = None               │                                                                                                              │
│   568 │   │   relation_remote=relation_remote,                                                 │       notice_id = None               │                                                                                                              │
│                                                                                                │        parallel = None               │                                                                                                              │
│                                                                                                │     relation_id = None               │                                                                                                              │
│                                                                                                │ relation_remote = None               │                                                                                                              │
│                                                                                                │          secret = None               │                                                                                                              │
│                                                                                                │     show_output = True               │                                                                                                              │
│                                                                                                │          target = 'postgresql-k8s/0' │                                                                                                              │
│                                                                                                ╰──────────────────────────────────────╯                                                                                                              │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:421 in _simulate_event                                                                                                                                                    │
│                                                                                                                                                                                                                                                      │
│   418 │   if not targets:                                                                      ╭─────────────────── locals ───────────────────╮                                                                                                      │
│   419 │   │   sys.exit(f"invalid target: {target!r} not found in {model or '<the current model │            check_name = None                 │                                                                                                      │
│   420 │                                                                                        │               dry_run = None                 │                                                                                                      │
│ ❱ 421 │   cmds = tuple(                                                                        │         emit_juju_log = True                 │                                                                                                      │
│   422 │   │   _build_command(                                                                  │          env_override = None                 │                                                                                                      │
│   423 │   │   │   unit=unit_name,                                                              │                 event = 'update-status'      │                                                                                                      │
│   424 │   │   │   event=event,                                                                 │                 model = None                 │                                                                                                      │
│                                                                                                │             notice_id = None                 │                                                                                                      │
│                                                                                                │     operator_dispatch = False                │                                                                                                      │
│                                                                                                │              parallel = None                 │                                                                                                      │
│                                                                                                │ print_captured_stderr = True                 │                                                                                                      │
│                                                                                                │ print_captured_stdout = True                 │                                                                                                      │
│                                                                                                │           relation_id = None                 │                                                                                                      │
│                                                                                                │       relation_remote = None                 │                                                                                                      │
│                                                                                                │    secret_id_or_label = None                 │                                                                                                      │
│                                                                                                │                target = 'postgresql-k8s/0'   │                                                                                                      │
│                                                                                                │               targets = ['postgresql-k8s/0'] │                                                                                                      │
│                                                                                                ╰──────────────────────────────────────────────╯                                                                                                      │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:433 in <genexpr>                                                                                                                                                          │
│                                                                                                                                                                                                                                                      │
│   430 │   │   │   secret_id_or_label=secret_id_or_label,                                       ╭─────────────────────────── locals ────────────────────────────╮                                                                                     │
│   431 │   │   │   operator_dispatch=operator_dispatch,                                         │                 .0 = <list_iterator object at 0x748f80dd4400> │                                                                                     │
│   432 │   │   │   env_override=env_override,                                                   │         check_name = None                                     │                                                                                     │
│ ❱ 433 │   │   │   has_dispatch=is_dispatch_aware(unit_name, model),                            │       env_override = None                                     │                                                                                     │
│   434 │   │   )                                                                                │              event = 'update-status'                          │                                                                                     │
│   435 │   │   for unit_name in targets                                                         │              model = None                                     │                                                                                     │
│   436 │   )                                                                                    │          notice_id = None                                     │                                                                                     │
│                                                                                                │  operator_dispatch = False                                    │                                                                                     │
│                                                                                                │        relation_id = None                                     │                                                                                     │
│                                                                                                │    relation_remote = None                                     │                                                                                     │
│                                                                                                │ secret_id_or_label = None                                     │                                                                                     │
│                                                                                                │          unit_name = 'postgresql-k8s/0'                       │                                                                                     │
│                                                                                                ╰───────────────────────────────────────────────────────────────╯                                                                                     │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/helpers.py:272 in is_dispatch_aware                                                                                                                                                               │
│                                                                                                                                                                                                                                                      │
│   269 │   except CalledProcessError as e:                                                      ╭─────────────────────────────────────────────── locals ────────────────────────────────────────────────╮                                             │
│   270 │   │   if e.returncode == 1:                                                            │         _model = ''                                                                                   │                                             │
│   271 │   │   │   return False                                                                 │            cmd = 'juju ssh postgresql-k8s/0 cat /var/lib/juju/agents/unit-postgresql-k8s-0/charm/d'+7 │                                             │
│ ❱ 272 │   │   raise e                                                                          │          model = None                                                                                 │                                             │
│   273                                                                                          │           unit = 'postgresql-k8s/0'                                                                   │                                             │
│   274                                                                                          │ unit_sanitized = 'unit-postgresql-k8s-0'                                                              │                                             │
│   275 @contextlib.contextmanager                                                               ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯                                             │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/helpers.py:267 in is_dispatch_aware                                                                                                                                                               │
│                                                                                                                                                                                                                                                      │
│   264 │   cmd = f"juju ssh{_model} {unit} cat /var/lib/juju/agents/{unit_sanitized}/charm/disp ╭─────────────────────────────────────────────── locals ────────────────────────────────────────────────╮                                             │
│   265 │   logger.debug(f"running {cmd}")                                                       │         _model = ''                                                                                   │                                             │
│   266 │   try:                                                                                 │            cmd = 'juju ssh postgresql-k8s/0 cat /var/lib/juju/agents/unit-postgresql-k8s-0/charm/d'+7 │                                             │
│ ❱ 267 │   │   check_call(shlex.split(cmd), stdout=PIPE, stderr=PIPE)                           │          model = None                                                                                 │                                             │
│   268 │   │   return True                                                                      │           unit = 'postgresql-k8s/0'                                                                   │                                             │
│   269 │   except CalledProcessError as e:                                                      │ unit_sanitized = 'unit-postgresql-k8s-0'                                                              │                                             │
│   270 │   │   if e.returncode == 1:                                                            ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯                                             │
│                                                                                                                                                                                                                                                      │
│ /usr/lib/python3.12/subprocess.py:413 in check_call                                                                                                                                                                                                  │
│                                                                                                                                                                                                                                                      │
│    410 │   │   cmd = kwargs.get("args")                                                         ╭──────────────────────────────────────────────────────── locals ────────────────────────────────────────────────────────╮                           │
│    411 │   │   if cmd is None:                                                                  │       cmd = ['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch']    │                           │
│    412 │   │   │   cmd = popenargs[0]                                                           │    kwargs = {'stdout': -1, 'stderr': -1}                                                                               │                           │
│ ❱  413 │   │   raise CalledProcessError(retcode, cmd)                                           │ popenargs = (['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch'],) │                           │
│    414 │   return 0                                                                             │   retcode = 2                                                                                                          │                           │
│    415                                                                                          ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯                           │
│    416                                                                                                                                                                                                                                               │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
CalledProcessError: Command '['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch']' returned non-zero exit status 2.



Manually creating the folder has helped a bit:


root@2xenrico:~# mkdir -p /root/.config/jhack

root@2xenrico:~# jhack fire postgresql-k8s/0 update-status
ERROR:jhack:It seems like the snap doesn't have access to /root/.local/share/juju;to grant it, run 'sudo snap connect jhack:dot-local-share-juju snapd'.Some Jhack commands will still work, but those that interact with the juju client will not.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:565 in simulate_event                                                                                                                                                     │
│                                                                                                                                                                                                                                                      │
│   562 │                                                                                        ╭─────────────── locals ───────────────╮                                                                                                              │
│   563 │   Especially useful in combination with jhack charm sync and/or debug-code/debug-hooks │      check_name = None               │                                                                                                              │
│   564 │   """                                                                                  │         dry_run = None               │                                                                                                              │
│ ❱ 565 │   return _simulate_event(                                                              │    env_override = None               │                                                                                                              │
│   566 │   │   target,                                                                          │           event = 'update-status'    │                                                                                                              │
│   567 │   │   event,                                                                           │           model = None               │                                                                                                              │
│   568 │   │   relation_remote=relation_remote,                                                 │       notice_id = None               │                                                                                                              │
│                                                                                                │        parallel = None               │                                                                                                              │
│                                                                                                │     relation_id = None               │                                                                                                              │
│                                                                                                │ relation_remote = None               │                                                                                                              │
│                                                                                                │          secret = None               │                                                                                                              │
│                                                                                                │     show_output = True               │                                                                                                              │
│                                                                                                │          target = 'postgresql-k8s/0' │                                                                                                              │
│                                                                                                ╰──────────────────────────────────────╯                                                                                                              │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:421 in _simulate_event                                                                                                                                                    │
│                                                                                                                                                                                                                                                      │
│   418 │   if not targets:                                                                      ╭─────────────────── locals ───────────────────╮                                                                                                      │
│   419 │   │   sys.exit(f"invalid target: {target!r} not found in {model or '<the current model │            check_name = None                 │                                                                                                      │
│   420 │                                                                                        │               dry_run = None                 │                                                                                                      │
│ ❱ 421 │   cmds = tuple(                                                                        │         emit_juju_log = True                 │                                                                                                      │
│   422 │   │   _build_command(                                                                  │          env_override = None                 │                                                                                                      │
│   423 │   │   │   unit=unit_name,                                                              │                 event = 'update-status'      │                                                                                                      │
│   424 │   │   │   event=event,                                                                 │                 model = None                 │                                                                                                      │
│                                                                                                │             notice_id = None                 │                                                                                                      │
│                                                                                                │     operator_dispatch = False                │                                                                                                      │
│                                                                                                │              parallel = None                 │                                                                                                      │
│                                                                                                │ print_captured_stderr = True                 │                                                                                                      │
│                                                                                                │ print_captured_stdout = True                 │                                                                                                      │
│                                                                                                │           relation_id = None                 │                                                                                                      │
│                                                                                                │       relation_remote = None                 │                                                                                                      │
│                                                                                                │    secret_id_or_label = None                 │                                                                                                      │
│                                                                                                │                target = 'postgresql-k8s/0'   │                                                                                                      │
│                                                                                                │               targets = ['postgresql-k8s/0'] │                                                                                                      │
│                                                                                                ╰──────────────────────────────────────────────╯                                                                                                      │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/utils/simulate_event.py:433 in <genexpr>                                                                                                                                                          │
│                                                                                                                                                                                                                                                      │
│   430 │   │   │   secret_id_or_label=secret_id_or_label,                                       ╭─────────────────────────── locals ────────────────────────────╮                                                                                     │
│   431 │   │   │   operator_dispatch=operator_dispatch,                                         │                 .0 = <list_iterator object at 0x70b4e8f5b640> │                                                                                     │
│   432 │   │   │   env_override=env_override,                                                   │         check_name = None                                     │                                                                                     │
│ ❱ 433 │   │   │   has_dispatch=is_dispatch_aware(unit_name, model),                            │       env_override = None                                     │                                                                                     │
│   434 │   │   )                                                                                │              event = 'update-status'                          │                                                                                     │
│   435 │   │   for unit_name in targets                                                         │              model = None                                     │                                                                                     │
│   436 │   )                                                                                    │          notice_id = None                                     │                                                                                     │
│                                                                                                │  operator_dispatch = False                                    │                                                                                     │
│                                                                                                │        relation_id = None                                     │                                                                                     │
│                                                                                                │    relation_remote = None                                     │                                                                                     │
│                                                                                                │ secret_id_or_label = None                                     │                                                                                     │
│                                                                                                │          unit_name = 'postgresql-k8s/0'                       │                                                                                     │
│                                                                                                ╰───────────────────────────────────────────────────────────────╯                                                                                     │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/helpers.py:272 in is_dispatch_aware                                                                                                                                                               │
│                                                                                                                                                                                                                                                      │
│   269 │   except CalledProcessError as e:                                                      ╭─────────────────────────────────────────────── locals ────────────────────────────────────────────────╮                                             │
│   270 │   │   if e.returncode == 1:                                                            │         _model = ''                                                                                   │                                             │
│   271 │   │   │   return False                                                                 │            cmd = 'juju ssh postgresql-k8s/0 cat /var/lib/juju/agents/unit-postgresql-k8s-0/charm/d'+7 │                                             │
│ ❱ 272 │   │   raise e                                                                          │          model = None                                                                                 │                                             │
│   273                                                                                          │           unit = 'postgresql-k8s/0'                                                                   │                                             │
│   274                                                                                          │ unit_sanitized = 'unit-postgresql-k8s-0'                                                              │                                             │
│   275 @contextlib.contextmanager                                                               ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯                                             │
│                                                                                                                                                                                                                                                      │
│ /snap/jhack/547/lib/python3.12/site-packages/jhack/helpers.py:267 in is_dispatch_aware                                                                                                                                                               │
│                                                                                                                                                                                                                                                      │
│   264 │   cmd = f"juju ssh{_model} {unit} cat /var/lib/juju/agents/{unit_sanitized}/charm/disp ╭─────────────────────────────────────────────── locals ────────────────────────────────────────────────╮                                             │
│   265 │   logger.debug(f"running {cmd}")                                                       │         _model = ''                                                                                   │                                             │
│   266 │   try:                                                                                 │            cmd = 'juju ssh postgresql-k8s/0 cat /var/lib/juju/agents/unit-postgresql-k8s-0/charm/d'+7 │                                             │
│ ❱ 267 │   │   check_call(shlex.split(cmd), stdout=PIPE, stderr=PIPE)                           │          model = None                                                                                 │                                             │
│   268 │   │   return True                                                                      │           unit = 'postgresql-k8s/0'                                                                   │                                             │
│   269 │   except CalledProcessError as e:                                                      │ unit_sanitized = 'unit-postgresql-k8s-0'                                                              │                                             │
│   270 │   │   if e.returncode == 1:                                                            ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯                                             │
│                                                                                                                                                                                                                                                      │
│ /usr/lib/python3.12/subprocess.py:413 in check_call                                                                                                                                                                                                  │
│                                                                                                                                                                                                                                                      │
│    410 │   │   cmd = kwargs.get("args")                                                         ╭──────────────────────────────────────────────────────── locals ────────────────────────────────────────────────────────╮                           │
│    411 │   │   if cmd is None:                                                                  │       cmd = ['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch']    │                           │
│    412 │   │   │   cmd = popenargs[0]                                                           │    kwargs = {'stdout': -1, 'stderr': -1}                                                                               │                           │
│ ❱  413 │   │   raise CalledProcessError(retcode, cmd)                                           │ popenargs = (['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch'],) │                           │
│    414 │   return 0                                                                             │   retcode = 2                                                                                                          │                           │
│    415                                                                                          ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯                           │
│    416                                                                                                                                                                                                                                               │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
CalledProcessError: Command '['juju', 'ssh', 'postgresql-k8s/0', 'cat', '/var/lib/juju/agents/unit-postgresql-k8s-0/charm/dispatch']' returned non-zero exit status 2.
root@2xenrico:~# sudo snap connect jhack:dot-local-share-juju snapd
root@2xenrico:~# jhack fire postgresql-k8s/0 update-status # finally all works here

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions