From a2167466273fd7cdd50c67cb82fdbfa333b30102 Mon Sep 17 00:00:00 2001
From: TerryHowe <terrylhowe@gmail.com>
Date: Wed, 4 Mar 2015 10:04:23 -0700
Subject: [PATCH] Add identity v3 catalog list

Change-Id: Id4c1371ca28b9fd884ec75061edca700fd69886c
---
 openstackclient/identity/v3/catalog.py        | 56 +++++++++++++
 .../tests/identity/v3/test_catalog.py         | 84 +++++++++++++++++++
 setup.cfg                                     |  2 +
 3 files changed, 142 insertions(+)
 create mode 100644 openstackclient/identity/v3/catalog.py
 create mode 100644 openstackclient/tests/identity/v3/test_catalog.py

diff --git a/openstackclient/identity/v3/catalog.py b/openstackclient/identity/v3/catalog.py
new file mode 100644
index 0000000000..0971366155
--- /dev/null
+++ b/openstackclient/identity/v3/catalog.py
@@ -0,0 +1,56 @@
+#   Licensed under the Apache License, Version 2.0 (the "License"); you may
+#   not use this file except in compliance with the License. You may obtain
+#   a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#   License for the specific language governing permissions and limitations
+#   under the License.
+#
+
+"""Identity v3 Service Catalog action implementations"""
+
+import logging
+
+from cliff import lister
+
+from openstackclient.common import utils
+
+
+def _format_endpoints(eps=None):
+    if not eps:
+        return ""
+    ret = ''
+    for ep in eps:
+        region = ep.get('region_id') or ep.get('region', '<none>')
+        ret += region + '\n'
+        ret += "  %s: %s\n" % (ep['interface'], ep['url'])
+    return ret
+
+
+class ListCatalog(lister.Lister):
+    """List services in the service catalog"""
+
+    log = logging.getLogger(__name__ + '.ListCatalog')
+
+    def take_action(self, parsed_args):
+        self.log.debug('take_action(%s)', parsed_args)
+
+        # This is ugly because if auth hasn't happened yet we need
+        # to trigger it here.
+        sc = self.app.client_manager.session.auth.get_auth_ref(
+            self.app.client_manager.session,
+        ).service_catalog
+
+        data = sc.get_data()
+        columns = ('Name', 'Type', 'Endpoints')
+        return (columns,
+                (utils.get_dict_properties(
+                    s, columns,
+                    formatters={
+                        'Endpoints': _format_endpoints,
+                    },
+                ) for s in data))
diff --git a/openstackclient/tests/identity/v3/test_catalog.py b/openstackclient/tests/identity/v3/test_catalog.py
new file mode 100644
index 0000000000..9adda86302
--- /dev/null
+++ b/openstackclient/tests/identity/v3/test_catalog.py
@@ -0,0 +1,84 @@
+#   Licensed under the Apache License, Version 2.0 (the "License"); you may
+#   not use this file except in compliance with the License. You may obtain
+#   a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#   License for the specific language governing permissions and limitations
+#   under the License.
+#
+
+import mock
+
+from openstackclient.identity.v3 import catalog
+from openstackclient.tests import utils
+
+
+class TestCatalog(utils.TestCommand):
+
+    fake_service = {
+        'id': 'qwertyuiop',
+        'type': 'compute',
+        'name': 'supernova',
+        'endpoints': [
+            {
+                'region': 'onlyone',
+                'url': 'https://public.example.com',
+                'interface': 'public',
+            },
+            {
+                'region_id': 'onlyone',
+                'url': 'https://admin.example.com',
+                'interface': 'admin',
+            },
+            {
+                'url': 'https://internal.example.com',
+                'interface': 'internal',
+            },
+        ],
+    }
+
+    def setUp(self):
+        super(TestCatalog, self).setUp()
+
+        self.sc_mock = mock.MagicMock()
+        self.sc_mock.service_catalog.get_data.return_value = [
+            self.fake_service,
+        ]
+
+        self.auth_mock = mock.MagicMock()
+        self.app.client_manager.session = self.auth_mock
+
+        self.auth_mock.auth.get_auth_ref.return_value = self.sc_mock
+
+
+class TestCatalogList(TestCatalog):
+
+    def setUp(self):
+        super(TestCatalogList, self).setUp()
+
+        # Get the command object to test
+        self.cmd = catalog.ListCatalog(self.app, None)
+
+    def test_catalog_list(self):
+        arglist = []
+        verifylist = []
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        # DisplayCommandBase.take_action() returns two tuples
+        columns, data = self.cmd.take_action(parsed_args)
+        self.sc_mock.service_catalog.get_data.assert_called_with()
+
+        collist = ('Name', 'Type', 'Endpoints')
+        self.assertEqual(collist, columns)
+        datalist = ((
+            'supernova',
+            'compute',
+            'onlyone\n  public: https://public.example.com\n'
+            'onlyone\n  admin: https://admin.example.com\n'
+            '<none>\n  internal: https://internal.example.com\n',
+        ), )
+        self.assertEqual(datalist, tuple(data))
diff --git a/setup.cfg b/setup.cfg
index 4da2bfa0e6..ff755f17c8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -183,6 +183,8 @@ openstack.identity.v2 =
 openstack.identity.v3 =
     access_token_create = openstackclient.identity.v3.token:CreateAccessToken
 
+    catalog_list = openstackclient.identity.v3.catalog:ListCatalog
+
     consumer_create = openstackclient.identity.v3.consumer:CreateConsumer
     consumer_delete = openstackclient.identity.v3.consumer:DeleteConsumer
     consumer_list = openstackclient.identity.v3.consumer:ListConsumer