Repository: StackStorm/st2

Issue:
`st2 pack install` connects to index.stackstorm.org even for local file installs
(Potentially related to #3771)

If I clone a StackStorm-Exchange repo to a local directory, and then attempt to install that repo using `st2 pack install file:////home/vagrant/mypack`, ST2 will attempt to connect to index.stackstorm.org.

If I don't have Internet access, this results in an error:

```
vagrant@bwcvagrant:~$ st2 pack install file:///home/vagrant/stackstorm-tesla.local/
ERROR: 400 Client Error: Bad Request
MESSAGE: No results from the index: tried https://index.stackstorm.org/v1/index.json.
Status: [
    {
        "url": "https://index.stackstorm.org/v1/index.json",
        "message": "ConnectionError(MaxRetryError(\"HTTPSConnectionPool(host='index.stackstorm.org', port=443): Max retries exceeded with url: /v1/index.json (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fa1864c8290>: Failed to establish a new connection: [Errno -2] Name or service not known',))\",),)",
        "error": "unresponsive",
        "packs": 0
    }
] for url: http://127.0.0.1:9101/v1/packs/index/search

vagrant@bwcvagrant:~$
```

I don't understand why `st2 pack install` is searching the index when it has been given a local file path to install from.


Discussion:
Reproduced on a firewalled system:

```
$ st2 pack install file:///$PWD
ERROR: 400 Client Error: Bad Request
MESSAGE: No results from the index: tried https://index.stackstorm.org/v1/index.json.
Status: [
    {
        "url": "https://index.stackstorm.org/v1/index.json",
        "message": "ConnectionError(MaxRetryError(\"HTTPSConnectionPool(host='index.stackstorm.org', port=443): Max retries exceeded with url: /v1/index.json (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x4dbf290>: Failed to establish a new connection: [Errno -2] Name or service not known',))\",),)",
        "error": "unresponsive",
        "packs": 0
    }
] for url: http://127.0.0.1:9101/v1/packs/index/search
```


Resolving patch:
diff --git a/st2client/st2client/commands/pack.py b/st2client/st2client/commands/pack.py
--- a/st2client/st2client/commands/pack.py
+++ b/st2client/st2client/commands/pack.py
@@ -200,11 +200,16 @@ def run(self, args, **kwargs):
 
     def _get_content_counts_for_pack(self, args, **kwargs):
         # Global content list, excluding "tests"
+        # Note: We skip this step for local packs
         pack_content = {'actions': 0, 'rules': 0, 'sensors': 0, 'aliases': 0, 'triggers': 0}
 
         if len(args.packs) == 1:
             args.pack = args.packs[0]
-            pack_info = self.manager.search(args, **kwargs)
+
+            if args.pack.startswith('file://'):
+                return
+
+            pack_info = self.manager.search(args, ignore_errors=True, **kwargs)
             content = getattr(pack_info, 'content', {})
 
             if content:
@@ -220,7 +225,11 @@ def _get_content_counts_for_pack(self, args, **kwargs):
             for pack in args.packs:
                 # args.pack required for search
                 args.pack = pack
-                pack_info = self.manager.search(args, **kwargs)
+
+                if args.pack.startswith('file://'):
+                    return
+
+                pack_info = self.manager.search(args, ignore_errors=True, **kwargs)
                 content = getattr(pack_info, 'content', {})
 
                 if content:
diff --git a/st2client/st2client/models/core.py b/st2client/st2client/models/core.py
--- a/st2client/st2client/models/core.py
+++ b/st2client/st2client/models/core.py
@@ -499,14 +499,19 @@ def remove(self, packs, **kwargs):
         return instance
 
     @add_auth_token_to_kwargs_from_env
-    def search(self, args, **kwargs):
+    def search(self, args, ignore_errors=False, **kwargs):
         url = '/%s/index/search' % (self.resource.get_url_path_name())
         if 'query' in vars(args):
             payload = {'query': args.query}
         else:
             payload = {'pack': args.pack}
-        response = self.client.post(url, payload, **kwargs)
+
+            response = self.client.post(url, payload, **kwargs)
+
         if response.status_code != http_client.OK:
+            if ignore_errors:
+                return None
+
             self.handle_error(response)
         data = response.json()
         if isinstance(data, list):


Test patch: