Skip to content

Feature: enable configured SSH destinations in remote Juju options #96

@LCVcode

Description

@LCVcode

Problem

When running remote Jockey commands with juju-jockey -H <hostname> ..., that hostname does not consider configured SSH hosts.

Proposed Feature

juju-jockey -H <hostname> should consider SSH configs to determine the host's IP.

Additional Context

Below is a quick example, which has been sanitized. In this example, I am only using the -H flag, which should not be an issue, so far as I understand. This problem seems to occur well before any other flags are even considered.

Here is a snippet of my SSH config:

Host infra.customer.cloud infra1.customer.cloud...
   Hostname 10.111.134.1
   ProxyJump vpn.customer.cloud

When I run the below command, it fails to find this IP address. Again, this is sanitized, but I ran the real thing on my end:

juju-jockey -H infra.customer.clouds units                     
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/lcv/.cache/pypoetry/virtualenvs/jockey-mWLLoW7i-py3.10/bin/juju-jockey:6 in <module>       │
│                                                                                                  │
│   3 from jockey.__main__ import main                                                             │
│   4                                                                                              │
│   5 if __name__ == '__main__':                                                                   │
│ ❱ 6 │   sys.exit(main())                                                                         │
│   7                                                                                              │
│                                                                                                  │
│ ╭──────────── locals ─────────────╮                                                              │
│ │ sys = <module 'sys' (built-in)> │                                                              │
│ ╰─────────────────────────────────╯                                                              │
│                                                                                                  │
│ /home/lcv/Work/repos/jockey/src/jockey/__main__.py:129 in main                                   │
│                                                                                                  │
│   126 │   │   cloud_juju = args.juju if "juju" in args else None                                 │
│   127 │   │                                                                                      │
│   128 │   │   # connect to the cloud and get the Juju status                                     │
│ ❱ 129 │   │   cloud = Cloud(host=cloud_host, user=cloud_user, doas=cloud_doas, timeout=cloud_t   │
│   130 │   │                                                                                      │
│   131 │   │   try:                                                                               │
│   132 │   │   │   status = cloud.juju_status                                                     │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │           args = Namespace(verbose=0, object='units', sudo=None, refresh=False,              │ │
│ │                  host='infra.customer.cloud')                                                │ │
│ │           argv = ['-H', 'infra.infra.customer.cloud', 'units']                               │ │
│ │          cache = FileCache(/home/lcv/.cache/jockey, max_age=300)                             │ │
│ │      cache_age = None                                                                        │ │
│ │      cache_dir = None                                                                        │ │
│ │  cache_refresh = False                                                                       │ │
│ │     cloud_doas = None                                                                        │ │
│ │     cloud_host = 'infra.customer.cloud'                                                      │ │
│ │     cloud_juju = None                                                                        │ │
│ │  cloud_timeout = None                                                                        │ │
│ │     cloud_user = None                                                                        │ │
│ │            obj = Object.UNIT                                                                 │ │
│ │ obj_expression = 'units'                                                                     │ │
│ │      obj_field = None                                                                        │ │
│ │      verbosity = 0                                                                           │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/lcv/Work/repos/jockey/src/jockey/cloud.py:130 in __init__                                  │
│                                                                                                  │
│   127 │   │   self.command_timeout = timeout                                                     │
│   128 │   │   self.original_host = host                                                          │
│   129 │   │                                                                                      │
│ ❱ 130 │   │   if Cloud.is_localhost_address(host):                                               │
│   131 │   │   │   config = CloudInvokeConfig()                                                   │
│   132 │   │   │   config.update(timeouts={"command": timeout})                                   │
│   133 │   │   │   Context.__init__(self, config)                                                 │
│                                                                                                  │
│ ╭───────────────────────── locals ──────────────────────────╮                                    │
│ │    args = ()                                              │                                    │
│ │   cache = None                                            │                                    │
│ │    doas = None                                            │                                    │
│ │    host = 'infra.infra.customer.cloud'                    │                                    │
│ │    juju = None                                            │                                    │
│ │  kwargs = {'user': None}                                  │                                    │
│ │    self = <repr-error 'maximum recursion depth exceeded'> │                                    │
│ │ timeout = None                                            │                                    │
│ ╰───────────────────────────────────────────────────────────╯                                    │
│                                                                                                  │
│ /home/lcv/Work/repos/jockey/src/jockey/cloud.py:206 in is_localhost_address                      │
│                                                                                                  │
│   203 │   │   return (                                                                           │
│   204 │   │   │   not address                                                                    │
│   205 │   │   │   or address in ("local", "localhost", "localhost.localdomain", "127.0.0.1", "
│ ❱ 206 │   │   │   or ip_address(address).is_loopback                                             │
│   207 │   │   )                                                                                  │
│   208 │                                                                                          │
│   209 │   def open(self) -> None:                                                                │
│                                                                                                  │
│ ╭──────────────────── locals ─────────────────────╮                                              │
│ │ address = 'infra.customer.cloud'                │                                              │
│ ╰─────────────────────────────────────────────────╯                                              │
│                                                                                                  │
│ /usr/lib/python3.10/ipaddress.py:54 in ip_address                                                │
│                                                                                                  │
│     51 │   except (AddressValueError, NetmaskValueError):                                        │
│     52 │   │   pass                                                                              │
│     53 │                                                                                         │
│ ❱   54 │   raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 address')        │
│     55                                                                                           │
│     56                                                                                           │
│     57 def ip_network(address, strict=True):                                                     │
│                                                                                                  │
│ ╭──────────────────── locals ─────────────────────╮                                              │
│ │ address = 'infra.customer.cloud'                │                                              │
│ ╰─────────────────────────────────────────────────╯                                              │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: 'infra.customer.cloud' does not appear to be an IPv4 or IPv6 address

Surprisingly, we're hitting a maximum recursion depth exception here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or requestpythonPull requests that update Python code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions