question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nested includes cause ConfigParseError

See original GitHub issue

Config structure:

.
├── config
└── subdir
    ├── foo
    │   ├── config
    └── includes

config:

Include subdir/includes

subdir/includes:

Include subdir/foo/config

expected result

no error. ssh at the command line works ssh_config man page states:

Files without absolute paths are assumed to be in ~/.ssh if included in a user configuration file

actual result

asyncssh.config.ConfigParseError: No match to pattern

Stack trace
Traceback (most recent call last):
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/bin/ocl", line 33, in <module>
    sys.exit(load_entry_point('OneDevEx', 'console_scripts', 'ocl')())
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/private/home/calebh/projects/OneDevEx/onedevex/aioutil.py", line 17, in wrapper
    loop.run_until_complete(root_task)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/asyncio/base_events.py", line 641, in run_until_complete
    return future.result()
  File "/private/home/calebh/projects/OneDevEx/onedevex/cli/commands/submit.py", line 29, in submit
    async with asyncssh.connect(cluster_host, known_hosts=None) as c, bootstrap(
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/misc.py", line 274, in __aenter__
    self._coro_result = await self._coro
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/connection.py", line 7682, in connect
    new_options = SSHClientConnectionOptions(options, config=config, host=host,
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/connection.py", line 6181, in __init__
    super().__init__(options=options, last_config=last_config, **kwargs)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/misc.py", line 350, in __init__
    self.prepare(**self.kwargs)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/connection.py", line 6881, in prepare
    config = SSHClientConfig.load(last_config, config, reload,
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 375, in load
    config.parse(Path(path))
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 335, in parse
    handler(self, option, args)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 137, in _include
    self.parse(path)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 335, in parse
    handler(self, option, args)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 134, in _include
    self._error('No match to pattern "%s"', pattern)
  File "/private/home/calebh/miniconda3/envs/onedevex-dev/lib/python3.10/site-packages/asyncssh/config.py", line 71, in _error
    raise ConfigParseError('%s line %s: %s' % (self._path, self._line_no,
asyncssh.config.ConfigParseError: /private/home/calebh/.ssh/fair_ssh/includes line 1: No match to pattern "fair_ssh/calebh/config"

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ronfcommented, Apr 16, 2022

This fix is now available in the AsyncSSH 2.10.1 release.

1reaction
ronfcommented, Mar 30, 2022

Thanks for the report!

I actually considered it a feature that includes to be relative to a parent include. However, after looking more closely at the OpenSSH behavior, I see that it appears to always treat paths as relative to ~/.ssh when parsing includes initiated from ~/.ssh/config.

Also, I noticed that a missing include file is not a fatal error in OpenSSH, so I’ve changed that to be just a debug message.

I believe the following patch will fix the problem:

diff --git a/asyncssh/config.py b/asyncssh/config.py
index 74927e4..49ea444 100644
--- a/asyncssh/config.py
+++ b/asyncssh/config.py
@@ -57,6 +57,7 @@ class SSHConfig:
         else:
             self._last_options = {}

+        self._default_path = Path('~', '.ssh').expanduser()
         self._path = Path()
         self._line_no = 0
         self._matching = True
@@ -126,12 +127,12 @@ class SSHConfig:
                 pattern = str(Path(*path.parts[1:]))
                 path = Path(path.anchor)
             else:
-                path = Path(self._path).parent
+                path = self._default_path

             paths = list(path.glob(pattern))

             if not paths:
-                self._error('No match to pattern "%s"', pattern)
+                logger.debug1('Config pattern "%s" matched no files', pattern)

             for path in paths:
                 self.parse(path)

If this works for you, let me know and I’ll check this into the “develop” branch.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nested keys don't work with AutomaticEnv · Issue #160 - GitHub
I came across this issue just now. For me, the root cause was strings.NewReplacer seems to only work with single-character strings. I.e. strings ......
Read more >
Error handling — Boto3 Docs 1.26.35 documentation - AWS
Any Boto3 clients you create will use these same statically defined exception classes. The most common botocore exception you'll encounter is ClientError ....
Read more >
nested-min-max / W3301 - Pylint 2.16.0-dev documentation
Nested calls ``min(1, min(2, 3))`` can be rewritten as ``min(1, 2, 3)``. Problematic code: print(min(1, min(2, 3))) # [nested-min-max].
Read more >
Viper - Go Packages
func (pe ConfigParseError) Error() string. type DecoderConfigOption ... Nested keys are returned with a v. ... Does not include extension.
Read more >
How to handle errors with boto3? - Stack Overflow
Use the response contained within the exception. Here is an example: import boto3 from botocore.exceptions import ClientError try: iam ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found