canonical / jhack

Chock-full of Juju hackery.
Apache License 2.0
48 stars 23 forks source link

jhack fire crashes if --model is specified: JSONDecodeError: Expecting value: line 1 column 1 (char 0) #140

Closed taurus-forever closed 3 months ago

taurus-forever commented 3 months ago

Hi,

The jhack fire ... update-status constantly crashes on my side if --model option used:

ubuntu@juju340:~$ snap list
Name             Version        Rev    Tracking            Publisher   Notes
bare             1.0            5      latest/stable       canonical✓  base
charmcraft       2.5.5          2453   latest/stable       canonical✓  classic
core18           20231027       2812   latest/stable       canonical✓  base
core20           20240111       2182   latest/stable       canonical✓  base
core22           20240111       1122   latest/stable       canonical✓  base
jhack            0.4.0.7        304    latest/edge         ppasotti    -
juju             3.4.0          26548  3.4/stable          canonical✓  -
lxd              5.0.3-9a1d904  27428  5.0/stable/…        canonical✓  -
microk8s         v1.27.11       6530   1.27-strict/stable  canonical✓  -
multipass-sshfs  1.1            145    latest/stable       canonical✓  -
snapd            2.61.2         21184  latest/stable       canonical✓  snapd
yq               v4.40.5        2450   latest/stable       mikefarah   -

ubuntu@juju340:~$ jhack fire db2/0 update-status
Fired update-status on db2/0.

ubuntu@juju340:~$ jhack fire db2/0 update-status -m az3
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /snap/jhack/304/lib/python3.8/site-packages/jhack/utils/simulate_event.py:247 in simulate_event  │
│                                                                                                  │
│   244 │                                                                                          │
│   245 │   Especially useful in combination with jhack charm sync and/or debug-code/debug-hooks   │
│   246 │   """                                                                                    │
│ ❱ 247 │   return _simulate_event(                                                                │
│   248 │   │   unit,                                                                              │
│   249 │   │   event,                                                                             │
│   250 │   │   relation_remote=relation_remote,                                                   │
│                                                                                                  │
│ ╭───────────── locals ──────────────╮                                                            │
│ │         dry_run = None            │                                                            │
│ │    env_override = []              │                                                            │
│ │           event = 'update-status' │                                                            │
│ │           model = 'az3'           │                                                            │
│ │ relation_remote = None            │                                                            │
│ │     show_output = True            │                                                            │
│ │            unit = 'db2/0'         │                                                            │
│ ╰───────────────────────────────────╯                                                            │
│                                                                                                  │
│ /snap/jhack/304/lib/python3.8/site-packages/jhack/utils/simulate_event.py:170 in _simulate_event │
│                                                                                                  │
│   167 │   │   raise RuntimeError("is juju installed?")                                           │
│   168 │                                                                                          │
│   169 │   juju_exec_cmd = "/usr/bin/" + ("juju-exec" if version >= (3, 0) else "juju-run")       │
│ ❱ 170 │   if get_substrate(_model) != "k8s":                                                     │
│   171 │   │   juju_exec_cmd = "sudo " + juju_exec_cmd                                            │
│   172 │                                                                                          │
│   173 │   cmd = f"juju ssh {_model}{unit} {juju_exec_cmd} -u {unit} {env} ./dispatch"            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │                _model = '-m az3 '                                                            │ │
│ │               dry_run = None                                                                 │ │
│ │         emit_juju_log = True                                                                 │ │
│ │                   env = 'JUJU_DISPATCH_PATH=hooks/update-status JUJU_MODEL_NAME=az3          │ │
│ │                         JUJU_UNIT_NAME=db2/0'                                                │ │
│ │          env_override = []                                                                   │ │
│ │                 event = 'update-status'                                                      │ │
│ │         juju_exec_cmd = '/usr/bin/juju-exec'                                                 │ │
│ │                 model = 'az3'                                                                │ │
│ │     operator_dispatch = False                                                                │ │
│ │ print_captured_stderr = True                                                                 │ │
│ │ print_captured_stdout = True                                                                 │ │
│ │       relation_remote = None                                                                 │ │
│ │                  unit = 'db2/0'                                                              │ │
│ │               version = (3, 4, 0)                                                            │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /snap/jhack/304/lib/python3.8/site-packages/jhack/helpers.py:73 in get_substrate                 │
│                                                                                                  │
│    70 │   cmd = f'juju show-model{f" {model}" if model else ""} --format=json'                   │
│    71 │   proc = JPopen(cmd.split())                                                             │
│    72 │   raw = proc.stdout.read().decode("utf-8")                                               │
│ ❱  73 │   model_info = jsn.loads(raw)                                                            │
│    74 │                                                                                          │
│    75 │   if not model:                                                                          │
│    76 │   │   model = list(model_info)[0]                                                        │
│                                                                                                  │
│ ╭────────────────────── locals ───────────────────────╮                                          │
│ │   cmd = 'juju show-model -m az3  --format=json'     │                                          │
│ │ model = '-m az3 '                                   │                                          │
│ │  proc = <subprocess.Popen object at 0x7f666b8dbe80> │                                          │
│ │   raw = ''                                          │                                          │
│ ╰─────────────────────────────────────────────────────╯                                          │
│                                                                                                  │
│ /usr/lib/python3.8/json/__init__.py:357 in loads                                                 │
│                                                                                                  │
│   354 │   if (cls is None and object_hook is None and                                            │
│   355 │   │   │   parse_int is None and parse_float is None and                                  │
│   356 │   │   │   parse_constant is None and object_pairs_hook is None and not kw):              │
│ ❱ 357 │   │   return _default_decoder.decode(s)                                                  │
│   358 │   if cls is None:                                                                        │
│   359 │   │   cls = JSONDecoder                                                                  │
│   360 │   if object_hook is not None:                                                            │
│                                                                                                  │
│ ╭───────── locals ─────────╮                                                                     │
│ │               cls = None │                                                                     │
│ │                kw = {}   │                                                                     │
│ │       object_hook = None │                                                                     │
│ │ object_pairs_hook = None │                                                                     │
│ │    parse_constant = None │                                                                     │
│ │       parse_float = None │                                                                     │
│ │         parse_int = None │                                                                     │
│ │                 s = ''   │                                                                     │
│ ╰──────────────────────────╯                                                                     │
│                                                                                                  │
│ /usr/lib/python3.8/json/decoder.py:337 in decode                                                 │
│                                                                                                  │
│   334 │   │   containing a JSON document).                                                       │
│   335 │   │                                                                                      │
│   336 │   │   """                                                                                │
│ ❱ 337 │   │   obj, end = self.raw_decode(s, idx=_w(s, 0).end())                                  │
│   338 │   │   end = _w(s, end).end()                                                             │
│   339 │   │   if end != len(s):                                                                  │
│   340 │   │   │   raise JSONDecodeError("Extra data", s, end)                                    │
│                                                                                                  │
│ ╭─────────────────────────────── locals ────────────────────────────────╮                        │
│ │   _w = <built-in method match of re.Pattern object at 0x7f666c7e7630> │                        │
│ │    s = ''                                                             │                        │
│ │ self = <json.decoder.JSONDecoder object at 0x7f666c801e80>            │                        │
│ ╰───────────────────────────────────────────────────────────────────────╯                        │
│                                                                                                  │
│ /usr/lib/python3.8/json/decoder.py:355 in raw_decode                                             │
│                                                                                                  │
│   352 │   │   try:                                                                               │
│   353 │   │   │   obj, end = self.scan_once(s, idx)                                              │
│   354 │   │   except StopIteration as err:                                                       │
│ ❱ 355 │   │   │   raise JSONDecodeError("Expecting value", s, err.value) from None               │
│   356 │   │   return obj, end                                                                    │
│   357                                                                                            │
│                                                                                                  │
│ ╭────────────────────────── locals ──────────────────────────╮                                   │
│ │  idx = 0                                                   │                                   │
│ │    s = ''                                                  │                                   │
│ │ self = <json.decoder.JSONDecoder object at 0x7f666c801e80> │                                   │
│ ╰────────────────────────────────────────────────────────────╯                                   │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
ubuntu@juju340:~$ 

STR:

* juju add-model test
* juju deploy mysql-k8s --trust # the charm you like
* jhack fire -m test mysql-k8s/0 update-status

BTW, the separate question: is firing event supported on the /leader?

ubuntu@juju340:~$ jhack fire db2/leader update-status 
ERROR:jhack.simulate_event:cmd juju ssh db2/leader /usr/bin/juju-exec -u db2/leader JUJU_DISPATCH_PATH=hooks/update-status JUJU_MODEL_NAME=az3 JUJU_UNIT_NAME=db2/leader ./dispatch terminated with 1
ERROR:jhack.simulate_event:stdout=b'\x1b[91mERROR\x1b[0m "db2/leader" is not a valid tag\r\n'
ERROR:jhack.simulate_event:stderr=b'ERROR command terminated with exit code 2\n'
Fired update-status on db2/leader.

ubuntu@juju340:~$ jhack fire db2/0 update-status 
Fired update-status on db2/0.

ubuntu@juju340:~$ juju status db2
Model  Controller  Cloud/Region        Version  SLA          Timestamp
az3    microk8s    microk8s/localhost  3.4.0    unsupported  17:57:14+01:00

App  Version                  Status  Scale  Charm      Channel         Rev  Address        Exposed  Message
db2  8.0.35-0ubuntu0.22.04.1  active      3  mysql-k8s  8.0/edge/arepl  126  10.152.183.70  no       

Unit    Workload  Agent  Address       Ports  Message
db2/0*  active    idle   10.1.204.195         Primary
db2/1   active    idle   10.1.204.231         
db2/2   active    idle   10.1.204.199         

Tnx!

PietroPasotti commented 3 months ago

Thanks for the report! Found the bug, it was a typo :) _model instead of model, the wrong variable was being passed to get_substrate.

As for the /leader syntax, none of the jhack commands supports it. You'll have to find the leader yourself via juju status. Is that something you'd like to see in jhack fire?

PietroPasotti commented 3 months ago

Fix is released to edge/beta.

PietroPasotti commented 3 months ago

Feel free to open a feature request for /leader support