Repository: dbt-labs/dbt-core

Issue:
dbt --version reports no plugins
### Describe the bug
When `dbt --version` is run from a package installed via pip, no plugins are reported.

### Steps To Reproduce
```
pip install dbt-core==0.17.0b1 dbt-snowflake==0.17.0b1
dbt --version
```


### Expected behavior
I expect to see plugin versions!

### System information
**Which database are you using dbt with?**
- [ ] postgres
- [ ] redshift
- [ ] bigquery
- [ ] snowflake
- [ ] other (specify: ____________)


**The output of `dbt --version`:**
```
$ dbt --version
installed version: 0.17.0-b1
   latest version: 0.16.1

Your version of dbt is ahead of the latest release!

Plugins:
```

**The operating system you're using:**
macos

**The output of `python --version`:**
`Python 3.8.2`

### Additional context
I think the issue here is that when pip installs multiple PEP420 packages they all end up in a single folder, unlike when you install locally in editable mode. So we need to teach `--version` to look at all the plugins in all the folders.


Discussion:

Resolving patch:
diff --git a/core/dbt/version.py b/core/dbt/version.py
--- a/core/dbt/version.py
+++ b/core/dbt/version.py
@@ -1,6 +1,9 @@
 import importlib
+import importlib.util
 import os
+import glob
 import json
+from typing import Iterator
 
 import requests
 
@@ -63,10 +66,24 @@ def get_version_information():
                 .format(version_msg, plugin_version_msg))
 
 
+def _get_adapter_plugin_names() -> Iterator[str]:
+    spec = importlib.util.find_spec('dbt.adapters')
+    # If None, then nothing provides an importable 'dbt.adapters', so we will
+    # not be reporting plugin versions today
+    if spec is None or spec.submodule_search_locations is None:
+        return
+    for adapters_path in spec.submodule_search_locations:
+        version_glob = os.path.join(adapters_path, '*', '__version__.py')
+        for version_path in glob.glob(version_glob):
+            # the path is like .../dbt/adapters/{plugin_name}/__version__.py
+            # except it could be \\ on windows!
+            plugin_root, _ = os.path.split(version_path)
+            _, plugin_name = os.path.split(plugin_root)
+            yield plugin_name
+
+
 def _get_dbt_plugins_info():
-    for path in importlib.util.find_spec('dbt').submodule_search_locations:
-        plugin_root, _ = os.path.split(path)
-        _, plugin_name = os.path.split(plugin_root)
+    for plugin_name in _get_adapter_plugin_names():
         if plugin_name == 'core':
             continue
         try:


Test patch:
diff --git a/test/unit/test_version.py b/test/unit/test_version.py
--- a/test/unit/test_version.py
+++ b/test/unit/test_version.py
@@ -113,15 +113,55 @@ def test_dbt_version_flag(self, mock_get, stderr):
             dbt.main.handle_and_check(['--version'])
         self.assertEqual(exc.exception.code, 0)
 
+    @patch('glob.glob', autospec=True)
     @patch('importlib.util.find_spec', autospec=True)
+    def test_get_adapter_plugin_names(self, mock_find_spec, mock_glob):
+        mock_submodule = unittest.mock.MagicMock()
+        mock_find_spec.return_value = mock_submodule
+        mock_submodule.submodule_search_locations = ['/tmp/dbt/adapters']
+
+        def glob_side_effect(path: str) -> str:
+            return [
+                path.replace('*', 'postgres'),
+                path.replace('*', 'snowflake'),
+            ]
+        mock_glob.side_effect = glob_side_effect
+        self.assertEqual(
+            list(dbt.version._get_adapter_plugin_names()),
+            ['postgres', 'snowflake'],
+        )
+
+        mock_find_spec.assert_called_once_with('dbt.adapters')
+
+    @patch('glob.glob', autospec=True)
+    @patch('importlib.util.find_spec', autospec=True)
+    def test_get_adapter_plugin_names(self, mock_find_spec, mock_glob):
+        mock_submodule = unittest.mock.MagicMock()
+        mock_find_spec.return_value = mock_submodule
+        mock_submodule.submodule_search_locations = [
+            '/tmp/dbt/plugins/postgres/dbt/adapters/', '/tmp/dbt/plugins/snowflake/dbt/adapters/'
+        ]
+
+        def glob_side_effect(path: str) -> str:
+            assert 'postgres' in path or 'snowflake' in path
+            if 'postgres' in path:
+                return [path.replace('*', 'postgres')]
+            elif 'snowflake' in path:
+                return [path.replace('*', 'snowflake')]
+        mock_glob.side_effect = glob_side_effect
+        self.assertEqual(
+            list(dbt.version._get_adapter_plugin_names()),
+            ['postgres', 'snowflake'],
+        )
+
+        mock_find_spec.assert_called_once_with('dbt.adapters')
+
+    @patch('dbt.version._get_adapter_plugin_names', autospec=True)
     @patch('importlib.import_module', autospec=True)
     def test_get_dbt_plugins_info_with_version_info(
-        self, mock_mod, mock_find_spec
+        self, mock_mod, mock_get_plugin_names
     ):
-        mock_submodule = unittest.mock.Mock()
-        mock_find_spec.return_value = mock_submodule
-        mock_submodule.submodule_search_locations = [
-            '/tmp/dbt/plugins/postgres/dbt', '/tmp/dbt/plugins/snowflake/dbt']
+        mock_get_plugin_names.return_value = ['postgres', 'snowflake']
         mod_version = unittest.mock.Mock()
         mock_mod.return_value = mod_version
         mod_version.version = '1.0'
@@ -129,7 +169,7 @@ def test_get_dbt_plugins_info_with_version_info(
             list(dbt.version._get_dbt_plugins_info()),
             [('postgres', '1.0'), ('snowflake', '1.0')]
         )
-        mock_find_spec.assert_called_once_with('dbt')
+        mock_get_plugin_names.assert_called_once_with()
         mock_mod.assert_has_calls([
             unittest.mock.call('dbt.adapters.postgres.__version__'),
             unittest.mock.call('dbt.adapters.snowflake.__version__')