canonical / jhack

Chock-full of Juju hackery.
Apache License 2.0
51 stars 24 forks source link

show-relation fails with KeyError: 'applications' #70

Closed dparv closed 1 year ago

dparv commented 1 year ago

Traceback: jhack show-relation vault:secrets barbican-vault:secrets-storage

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:651 in                  │
│ sync_show_relation                                                                               │
│                                                                                                  │
│   648 │                                                                                          │
│   649 │   $ jhack utils show-relation my_app:relation_name other_app:other_name                  │
│   650 │   """                                                                                    │
│ ❱ 651 │   return _sync_show_relation(                                                            │
│   652 │   │   endpoint1=endpoint1,                                                               │
│   653 │   │   endpoint2=endpoint2,                                                               │
│   654 │   │   n=n,                                                                               │
│                                                                                                  │
│ ╭──────────────────────── locals ────────────────────────╮                                       │
│ │               color = 'auto'                           │                                       │
│ │           endpoint1 = 'vault:secrets'                  │                                       │
│ │           endpoint2 = 'barbican-vault:secrets-storage' │                                       │
│ │ hide_empty_databags = False                            │                                       │
│ │               model = None                             │                                       │
│ │                   n = None                             │                                       │
│ │      show_juju_keys = False                            │                                       │
│ │               watch = False                            │                                       │
│ ╰────────────────────────────────────────────────────────╯                                       │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:688 in                  │
│ _sync_show_relation                                                                              │
│                                                                                                  │
│   685 │   while True:                                                                            │
│   686 │   │   start = time.time()                                                                │
│   687 │   │                                                                                      │
│ ❱ 688 │   │   table = asyncio.run(                                                               │
│   689 │   │   │   render_relation(                                                               │
│   690 │   │   │   │   endpoint1,                                                                 │
│   691 │   │   │   │   endpoint2,                                                                 │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │               color = 'auto'                                                                 │ │
│ │             Console = <class 'rich.console.Console'>                                         │ │
│ │             console = <console width=211 ColorSystem.EIGHT_BIT>                              │ │
│ │           endpoint1 = 'vault:secrets'                                                        │ │
│ │           endpoint2 = 'barbican-vault:secrets-storage'                                       │ │
│ │ hide_empty_databags = False                                                                  │ │
│ │               model = None                                                                   │ │
│ │                   n = None                                                                   │ │
│ │                rich = <module 'rich' from                                                    │ │
│ │                       '/snap/jhack/205/lib/python3.8/site-packages/rich/__init__.py'>        │ │
│ │      show_juju_keys = False                                                                  │ │
│ │               start = 1679397896.4327023                                                     │ │
│ │               watch = False                                                                  │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /usr/lib/python3.8/asyncio/runners.py:44 in run                                                  │
│                                                                                                  │
│   41 │   │   events.set_event_loop(loop)                                                         │
│   42 │   │   if debug is not None:                                                               │
│   43 │   │   │   loop.set_debug(debug)                                                           │
│ ❱ 44 │   │   return loop.run_until_complete(main)                                                │
│   45 │   finally:                                                                                │
│   46 │   │   try:                                                                                │
│   47 │   │   │   _cancel_all_tasks(loop)                                                         │
│                                                                                                  │
│ ╭──────────────────────────────── locals ────────────────────────────────╮                       │
│ │ debug = None                                                           │                       │
│ │  loop = <_UnixSelectorEventLoop running=False closed=True debug=False> │                       │
│ │  main = <coroutine object render_relation at 0x7fb05c2c1040>           │                       │
│ ╰────────────────────────────────────────────────────────────────────────╯                       │
│                                                                                                  │
│ /usr/lib/python3.8/asyncio/base_events.py:616 in run_until_complete                              │
│                                                                                                  │
│    613 │   │   if not future.done():                                                             │
│    614 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')             │
│    615 │   │                                                                                     │
│ ❱  616 │   │   return future.result()                                                            │
│    617 │                                                                                         │
│    618 │   def stop(self):                                                                       │
│    619 │   │   """Stop running the event loop.                                                   │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   future = <Task finished name='Task-1' coro=<render_relation() done, defined at             │ │
│ │            /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:473>     │ │
│ │            exception=KeyError('applications')>                                               │ │
│ │ new_task = True                                                                              │ │
│ │     self = <_UnixSelectorEventLoop running=False closed=True debug=False>                    │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:533 in render_relation  │
│                                                                                                  │
│   530 │   │   if not (endpoint1 and endpoint2):                                                  │
│   531 │   │   │   raise RuntimeError("invalid usage: provide two endpoints.")                    │
│   532 │   │                                                                                      │
│ ❱ 533 │   │   data = get_relation_data(                                                          │
│   534 │   │   │   provider_endpoint=endpoint1,                                                   │
│   535 │   │   │   requirer_endpoint=endpoint2,                                                   │
│   536 │   │   │   include_default_juju_keys=include_default_juju_keys,                           │
│                                                                                                  │
│ ╭─────────────────────────── locals ───────────────────────────╮                                 │
│ │                 endpoint1 = 'vault:secrets'                  │                                 │
│ │                 endpoint2 = 'barbican-vault:secrets-storage' │                                 │
│ │       hide_empty_databags = False                            │                                 │
│ │ include_default_juju_keys = False                            │                                 │
│ │                     model = None                             │                                 │
│ │                         n = None                             │                                 │
│ │             relation_type = None                             │                                 │
│ ╰──────────────────────────────────────────────────────────────╯                                 │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:398 in                  │
│ get_relation_data                                                                                │
│                                                                                                  │
│   395 │                                                                                          │
│   396 │   >>> get_relation_data('prometheus/0:ingress', 'traefik/1:ingress-per-unit')            │
│   397 │   """                                                                                    │
│ ❱ 398 │   provider_data = get_content(                                                           │
│   399 │   │   provider_endpoint, requirer_endpoint, include_default_juju_keys, model=model       │
│   400 │   )                                                                                      │
│   401 │   requirer_data = get_content(                                                           │
│                                                                                                  │
│ ╭─────────────────────────── locals ───────────────────────────╮                                 │
│ │ include_default_juju_keys = False                            │                                 │
│ │                     model = None                             │                                 │
│ │         provider_endpoint = 'vault:secrets'                  │                                 │
│ │         requirer_endpoint = 'barbican-vault:secrets-storage' │                                 │
│ ╰──────────────────────────────────────────────────────────────╯                                 │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:258 in get_content      │
│                                                                                                  │
│   255 │   other_app_name, _ = other_url.split("/") if "/" in other_url else (other_url, None)    │
│   256 │   this_app_name, _ = this_url.split("/") if "/" in this_url else (this_url, None)        │
│   257 │                                                                                          │
│ ❱ 258 │   app_name, units, meta = get_app_name_and_units(                                        │
│   259 │   │   this_url, this_endpoint, other_app_name, other_endpoint, model                     │
│   260 │   )                                                                                      │
│   261                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────── locals ────────────────────────────╮                                │
│ │                         _ = None                              │                                │
│ │ include_default_juju_keys = False                             │                                │
│ │                     model = None                              │                                │
│ │                       obj = 'vault:secrets'                   │                                │
│ │            other_app_name = 'barbican-vault'                  │                                │
│ │            other_endpoint = 'secrets-storage'                 │                                │
│ │                 other_obj = 'barbican-vault:secrets-storage'  │                                │
│ │                 other_url = 'barbican-vault'                  │                                │
│ │             relation_type = <RelationType.regular: 'regular'> │                                │
│ │             this_app_name = 'vault'                           │                                │
│ │             this_endpoint = 'secrets'                         │                                │
│ │                  this_url = 'vault'                           │                                │
│ ╰───────────────────────────────────────────────────────────────╯                                │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:228 in                  │
│ get_app_name_and_units                                                                           │
│                                                                                                  │
│   225 │   """Get app name and unit count from url; url is either `app_name/0` or `app_name`.""   │
│   226 │   app_name, unit_id = url.split("/") if "/" in url else (url, None)                      │
│   227 │                                                                                          │
│ ❱ 228 │   meta = get_metadata_from_status(                                                       │
│   229 │   │   app_name, relation_name, other_app_name, other_relation_name, model=model          │
│   230 │   )                                                                                      │
│   231 │   if unit_id is not None:                                                                │
│                                                                                                  │
│ ╭──────────────── locals ─────────────────╮                                                      │
│ │            app_name = 'vault'           │                                                      │
│ │               model = None              │                                                      │
│ │      other_app_name = 'barbican-vault'  │                                                      │
│ │ other_relation_name = 'secrets-storage' │                                                      │
│ │       relation_name = 'secrets'         │                                                      │
│ │             unit_id = None              │                                                      │
│ │                 url = 'vault'           │                                                      │
│ ╰─────────────────────────────────────────╯                                                      │
│                                                                                                  │
│ /snap/jhack/205/lib/python3.8/site-packages/jhack/utils/show_relation.py:176 in                  │
│ get_metadata_from_status                                                                         │
│                                                                                                  │
│   173 ):                                                                                         │
│   174 │   status = _juju_status(app_name, model=model, json=True)                                │
│   175 │   # machine status json output apparently has no 'scale'... -_-                          │
│ ❱ 176 │   app_status = status["applications"][app_name]                                          │
│   177 │   if app_status.get('subordinate-to'):                                                   │
│   178 │   │   units = {}                                                                         │
│   179 │   │   for other_unit in status["applications"][other_app_name]['units'].values():        │
│                                                                                                  │
│ ╭──────────────── locals ─────────────────╮                                                      │
│ │            app_name = 'vault'           │                                                      │
│ │               model = None              │                                                      │
│ │      other_app_name = 'barbican-vault'  │                                                      │
│ │ other_relation_name = 'secrets-storage' │                                                      │
│ │       relation_name = 'secrets'         │                                                      │
│ │              status = {}                │                                                      │
│ ╰─────────────────────────────────────────╯                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
PietroPasotti commented 1 year ago

the issue seems to be that juju status returns an empty dict. I've heard of that issue before but I'm not sure in what context. can you try running manually juju status --format json and see if you get any values out?

dparv commented 1 year ago

It returns plenty of things, and applications is there

juju status --format json | jq '.applications | keys[]'
"aodh"
"aodh-mysql-router"
"barbican"
"barbican-mysql-router"
"barbican-vault"
"bcache-tuning"
"ceilometer"
"ceilometer-agent"
"ceph-dashboard"
"ceph-fs"
"ceph-mon"
"ceph-osd-flash"
"ceph-osd-hdd"
"ceph-radosgw"
"cinder"
"cinder-ceph-flash"
"cinder-ceph-hdd"
"cinder-mysql-router"
"cos-proxy-lite"
"designate"
"designate-bind"
"designate-mysql-router"
"easyrsa"
"etcd"
"filebeat"
"glance"
"glance-mysql-router"
"glance-simplestreams-sync"
"gnocchi"
"gnocchi-mysql-router"
"golang-openstack-exporter"
"hacluster-aodh"
"hacluster-barbican"
"hacluster-ceilometer"
"hacluster-cinder"
"hacluster-designate"
"hacluster-glance"
"hacluster-gnocchi"
"hacluster-heat"
"hacluster-horizon"
"hacluster-keystone"
"hacluster-neutron"
"hacluster-nova"
"hacluster-octavia"
"hacluster-placement"
"hacluster-radosgw"
"hacluster-vault"
"heat"
"heat-mysql-router"
"hw-health"
"juju-lint"
"keystone"
"keystone-mysql-router"
"landscape-client"
"lldpd"
"logrotated"
"memcached"
"mysql-innodb-cluster"
"neutron-api"
"neutron-api-mysql-router"
"neutron-api-plugin-ovn"
"nova-cloud-controller"
"nova-cloud-controller-mysql-router"
"nova-compute-kvm"
"nova-compute-kvm-ctrl"
"nova-compute-kvm-sriov"
"nrpe"
"ntp"
"octavia"
"octavia-dashboard"
"octavia-diskimage-retrofit"
"octavia-mysql-router"
"octavia-ovn-chassis"
"openstack-dashboard"
"openstack-dashboard-mysql-router"
"openstack-service-checks"
"ovn-central"
"ovn-chassis"
"ovn-chassis-sriov"
"placement"
"placement-mysql-router"
"prometheus-grok-exporter"
"prometheus-libvirt-exporter"
"prometheus-openstack-exporter"
"public-policy-routing"
"rabbitmq-server"
"sysconfig"
"sysconfig-ctrl"
"sysconfig-sriov"
"telegraf"
"ubuntu-advantage"
"vault"
"vault-mysql-router"
PietroPasotti commented 1 year ago

snap connections jhack?

PietroPasotti commented 1 year ago

TLDR: jhack assumes that unless you specify a model with --model, the applications you're trying to show relations for are in the 'current model', i.e. what your local juju client is switched to. It seems that @dparv and colleagues are relying on a JUJU_MODEL envvar to target different models instead of juju-switching to them. jhack currently is unaware of that envvar.

Closing this as a won't fix, but if you think jhack should consider JUJU_MODEL, we can open a new feature request and discuss there.