class TestCompletion(unittest.TestCase):

    def setUp(self):
        self.mgr = CommandManager()
        self.cmd = TestCmd('test-cmd')
        self.mgr.add('test-cmd', self.cmd)

    def test_bad_cmd(self):
        with self.assertRaises(CommandInvalid):
            CommandParser('foo -h')
        with self.assertRaises(CommandInvalid):
            CommandParser('bar ')
        with self.assertRaises(CommandNotFound):
            CommandParser('')
        with self.assertRaises(CommandNotFound):
            CommandParser('ex')

    def test_cmd(self):
        parser = CommandParser('test-cmd')
        self.assertEqual(parser.cmd, self.mgr.get('test-cmd'))
        self.assertEqual(parser.cmd_name, 'test-cmd')

    def test_option_parsing(self):
        parser = CommandParser('test-cmd -h')
        self.assertEqual(len(list(parser.used_options)), 1)
        expected = ['--bar', '--foo', '-l']
        parsed = [a.option_strings[0] for a in parser.available_options]
        self.assertEqual(parsed, expected)

        parser = CommandParser('test-cmd --foo -h')
        self.assertEqual(len(list(parser.used_options)), 2)
        expected = ['--bar', '-l']
        parsed = [a.option_strings[0] for a in parser.available_options]
        self.assertEqual(parsed, expected)
class TestParser(unittest.TestCase):
    def setUp(self):
        self.mgr = CommandManager()
        self.cmd = TestCmd('test-cmd')
        self.cmd2 = TestCmd2('test-cmd2')
        self.mgr.add('test-cmd', self.cmd)
        self.mgr.add('test-cmd2', self.cmd2)

    def test_bad_cmd(self):
        with self.assertRaises(CommandInvalid):
            CommandParser(Document('foo -h'))
        with self.assertRaises(CommandInvalid):
            CommandParser(Document('bar '))
        with self.assertRaises(CommandNotFound):
            CommandParser(Document())
        with self.assertRaises(CommandNotFound):
            CommandParser(Document('ex'))

    def test_cmd(self):
        parser = CommandParser(Document('test-cmd'))
        self.assertEqual(parser.cmd, self.mgr.get('test-cmd'))
        self.assertEqual(parser.cmd_name, 'test-cmd')

    def test_option_parsing(self):
        parser = CommandParser(Document('test-cmd -h'))
        self.assertEqual(len(list(parser.used_options)), 0)
        expected = ['-l', '--foo', '--bar']
        parsed = [
            o.short_name or o.long_name for o in parser.available_options
        ]
        self.assertEqual(parsed, expected)

        parser = CommandParser(Document('test-cmd --bar -h'))
        self.assertEqual(len(list(parser.used_options)), 1)
        expected = ['-l', '--foo', '--bar']
        parsed = [
            o.short_name or o.long_name for o in parser.available_options
        ]
        self.assertEqual(parsed, expected)

    def test_arg_parsing(self):
        parser = CommandParser(
            Document('test-cmd --foo bar arg1_value -l arg2_value '))
        self.assertEqual(list(parser.used_args),
                         [self.cmd.args['arg1'], self.cmd.args['arg2']])
        parser = CommandParser(Document('test-cmd arg1_value -l'))
        self.assertEqual(list(parser.used_args), [self.cmd.args['arg1']])
        self.assertEqual(list(parser.available_args), [self.cmd.args['arg2']])

        parser = CommandParser(Document('test-cmd2 arg1_value -l'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
        parser = CommandParser(Document('test-cmd2 arg1_value -l arg2_value'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
        parser = CommandParser(
            Document('test-cmd2 arg1_value -l arg2_value arg2_value2'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
class TestParser(unittest.TestCase):

    def setUp(self):
        self.mgr = CommandManager()
        self.cmd = TestCmd('test-cmd')
        self.cmd2 = TestCmd2('test-cmd2')
        self.mgr.add('test-cmd', self.cmd)
        self.mgr.add('test-cmd2', self.cmd2)

    def test_bad_cmd(self):
        with self.assertRaises(CommandInvalid):
            CommandParser(Document('foo -h'))
        with self.assertRaises(CommandInvalid):
            CommandParser(Document('bar '))
        with self.assertRaises(CommandNotFound):
            CommandParser(Document())
        with self.assertRaises(CommandNotFound):
            CommandParser(Document('ex'))

    def test_cmd(self):
        parser = CommandParser(Document('test-cmd'))
        self.assertEqual(parser.cmd, self.mgr.get('test-cmd'))
        self.assertEqual(parser.cmd_name, 'test-cmd')

    def test_option_parsing(self):
        parser = CommandParser(Document('test-cmd -h'))
        self.assertEqual(len(list(parser.used_options)), 0)
        expected = ['-l', '--foo', '--bar']
        parsed = [o.short_name or o.long_name for o in parser.available_options]
        self.assertEqual(parsed, expected)

        parser = CommandParser(Document('test-cmd --bar -h'))
        self.assertEqual(len(list(parser.used_options)), 1)
        expected = ['-l', '--foo', '--bar']
        parsed = [o.short_name or o.long_name for o in parser.available_options]
        self.assertEqual(parsed, expected)

    def test_arg_parsing(self):
        parser = CommandParser(Document('test-cmd --foo bar arg1_value -l arg2_value '))
        self.assertEqual(list(parser.used_args), [self.cmd.args['arg1'], self.cmd.args['arg2']])
        parser = CommandParser(Document('test-cmd arg1_value -l'))
        self.assertEqual(list(parser.used_args), [self.cmd.args['arg1']])
        self.assertEqual(list(parser.available_args), [self.cmd.args['arg2']])

        parser = CommandParser(Document('test-cmd2 arg1_value -l'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
        parser = CommandParser(Document('test-cmd2 arg1_value -l arg2_value'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
        parser = CommandParser(Document('test-cmd2 arg1_value -l arg2_value arg2_value2'))
        self.assertEqual(list(parser.available_args), [self.cmd2.args['arg2']])
Beispiel #4
0
class TestParser(unittest.TestCase):
    def setUp(self):
        self.mgr = CommandManager()
        self.cmd = TestCmd('test-cmd')
        self.mgr.add('test-cmd', self.cmd)

    def test_bad_cmd(self):
        with self.assertRaises(CommandInvalid):
            CommandParser('foo -h')
        with self.assertRaises(CommandInvalid):
            CommandParser('bar ')
        with self.assertRaises(CommandNotFound):
            CommandParser('')
        with self.assertRaises(CommandNotFound):
            CommandParser('ex')

    def test_cmd(self):
        parser = CommandParser('test-cmd')
        self.assertEqual(parser.cmd, self.mgr.get('test-cmd'))
        self.assertEqual(parser.cmd_name, 'test-cmd')

    def test_option_parsing(self):
        parser = CommandParser('test-cmd -h')
        self.assertEqual(len(list(parser.used_options)), 0)
        expected = ['--bar', '--foo', '-l']
        parsed = [
            o.short_name or o.long_name for o in parser.available_options
        ]
        self.assertEqual(parsed, expected)

        parser = CommandParser('test-cmd --bar -h')
        self.assertEqual(len(list(parser.used_options)), 1)
        expected = ['--bar', '--foo', '-l']
        parsed = [
            o.short_name or o.long_name for o in parser.available_options
        ]
        self.assertEqual(parsed, expected)
Beispiel #5
0
class TestCommand(CLITest):
    def setUp(self):
        CLITest.setUp(self)
        self.mgr = CommandManager()
        self.mgr.load_namespace('contrail_api_cli.shell_command')
        self.mgr.add('cmd', Cmd('cmd'))
        self.mgr.add('arg-test', ArgTest('arg-test'))

    def test_cd(self):
        self.mgr.get('cd')('foo')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('bar')
        self.assertEqual(Context().shell.current_path, Path('/foo/bar'))
        self.mgr.get('cd')('..')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('/')
        self.assertEqual(Context().shell.current_path, Path('/'))

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_root_collection(self, mock_session):
        Context().shell.current_path = Path('/')
        mock_session.get_json.return_value = {
            'href':
            self.BASE,
            'links': [{
                'link': {
                    'href': self.BASE + '/instance-ips',
                    'path': Path('/instance-ips'),
                    'name': 'instance-ip',
                    'rel': 'collection'
                }
            }, {
                'link': {
                    'href': self.BASE + '/instance-ip',
                    'path': Path('/instance-ip'),
                    'name': 'instance-ip',
                    'rel': 'resource-base'
                }
            }]
        }
        result = self.mgr.get('ls')()
        self.assertEqual('instance-ip', result)

        mock_session.get_json.side_effect = [{
            'href':
            self.BASE,
            'links': [{
                'link': {
                    'href': self.BASE + '/foos',
                    'path': Path('/foos'),
                    'name': 'foo',
                    'rel': 'collection'
                }
            }, {
                'link': {
                    'href': self.BASE + '/bars',
                    'path': Path('/bars'),
                    'name': 'bar',
                    'rel': 'collection'
                }
            }]
        }, {
            'foos': [{
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724'
            }, {
                'href':
                self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a'
            }]
        }, {
            'bars': [{
                'href':
                self.BASE + '/bar/ffe8de43-a141-4336-8d70-bf970813bbf7',
                'uuid': 'ffe8de43-a141-4336-8d70-bf970813bbf7'
            }]
        }]

        Context().shell.current_path = Path('/')
        expected_result = """foo/ec1afeaa-8930-43b0-a60a-939f23a50724
foo/c2588045-d6fb-4f37-9f46-9451f653fb6a
bar/ffe8de43-a141-4336-8d70-bf970813bbf7"""
        result = self.mgr.get('ls')(paths=['*'])
        self.assertEqual(result, expected_result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_collection(self, mock_session):
        mock_session.get_json.return_value = {
            'foos': [{
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724'
            }, {
                'href':
                self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a'
            }]
        }

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('ls')()
        self.assertEqual(
            '\n'.join([
                'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'c2588045-d6fb-4f37-9f46-9451f653fb6a'
            ]), result)

        Context().shell.current_path = Path('/')
        result = self.mgr.get('ls')(paths=['foo'])
        self.assertEqual(
            '\n'.join([
                'foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'
            ]), result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_ls(self, mock_session):
        mock_session.get_json.return_value = {
            'foo': {
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
            }
        }
        Context().shell.current_path = Path('/foo')
        expected_result = 'ec1afeaa-8930-43b0-a60a-939f23a50724'
        result = self.mgr.get('ls')(
            paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'])
        self.assertEqual(result, expected_result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_long_ls(self, mock_session):
        mock_session.id_to_fqname.return_value = {
            'type':
            'foo',
            'fq_name':
            FQName('default-project:foo:ec1afeaa-8930-43b0-a60a-939f23a50724')
        }
        mock_session.get_json.return_value = {
            'foo': {
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid':
                'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'fq_name': [
                    'default-project', 'foo',
                    'ec1afeaa-8930-43b0-a60a-939f23a50724'
                ],
                'prop': {
                    'foo': False,
                    'bar': [1, 2, 3]
                }
            }
        }
        Context().shell.current_path = Path('/')
        result = self.mgr.get('ls')(
            paths=['foo/ec1afeaa-8930-43b0-a60a-939f23a50724'], int=True)
        expected_result = "foo/ec1afeaa-8930-43b0-a60a-939f23a50724  default-project:foo:ec1afeaa-8930-43b0-a60a-939f23a50724"
        self.assertEqual(result, expected_result)

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('ls')(
            paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'],
            int=True,
            fields=['prop'])
        expected_results = [
            "ec1afeaa-8930-43b0-a60a-939f23a50724  foo=False|bar=1,2,3",
            "ec1afeaa-8930-43b0-a60a-939f23a50724  bar=1,2,3|foo=False"
        ]

        self.assertTrue(any([result == r for r in expected_results]))

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_parent_uuid_ls(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        self.mgr.get('ls')(paths=['foo'])
        mock_session.get_json.assert_called_with(self.BASE + '/foos')
        self.mgr.get('ls')(paths=['foo'],
                           parent_uuid='1ad831be-3b21-4870-aadf-8efc2b0a480d')
        mock_session.get_json.assert_called_with(
            self.BASE + '/foos',
            parent_id='1ad831be-3b21-4870-aadf-8efc2b0a480d')

    @mock.patch('contrail_api_cli.commands.cat.highlight_json')
    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_cat(self, mock_session, mock_highlight_json):
        # bind original method to mock_session
        mock_session.id_to_fqname = client.ContrailAPISession.id_to_fqname.__get__(
            mock_session)
        mock_session.make_url = client.ContrailAPISession.make_url.__get__(
            mock_session)

        # called by id_to_fqname
        def post(url, json=None):
            if json['uuid'] == "ec1afeaa-8930-43b0-a60a-939f23a50724":
                return {
                    "type": "foo",
                    "fq_name": ["foo", "ec1afeaa-8930-43b0-a60a-939f23a50724"]
                }
            if json['uuid'] == "15315402-8a21-4116-aeaa-b6a77dceb191":
                return {
                    "type": "bar",
                    "fq_name": ["bar", "15315402-8a21-4116-aeaa-b6a77dceb191"]
                }

        mock_session.post_json.side_effect = post
        mock_highlight_json.side_effect = lambda d: d
        mock_session.get_json.return_value = {
            'foo': {
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid':
                'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'attr':
                None,
                'fq_name': ['foo', 'ec1afeaa-8930-43b0-a60a-939f23a50724'],
                'bar_refs': [{
                    'href':
                    self.BASE + '/bar/15315402-8a21-4116-aeaa-b6a77dceb191',
                    'uuid':
                    '15315402-8a21-4116-aeaa-b6a77dceb191',
                    'to': ['bar', '15315402-8a21-4116-aeaa-b6a77dceb191']
                }]
            }
        }
        Context().shell.current_path = Path('/foo')
        expected_resource = Resource(
            'foo',
            uuid='ec1afeaa-8930-43b0-a60a-939f23a50724',
            href=self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
            attr=None,
            fq_name='foo:ec1afeaa-8930-43b0-a60a-939f23a50724')
        expected_resource['bar_refs'] = [
            Resource('bar',
                     uuid='15315402-8a21-4116-aeaa-b6a77dceb191',
                     href=self.BASE +
                     '/bar/15315402-8a21-4116-aeaa-b6a77dceb191',
                     to=['bar', '15315402-8a21-4116-aeaa-b6a77dceb191'])
        ]
        result = self.mgr.get('cat')(
            paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'])
        self.assertEqual(expected_resource.json(), result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_notfound_fqname_ls(self, mock_session):
        fq_name = 'default-domain:foo'
        Context().shell.current_path = Path('/foo')
        mock_session.fqname_to_id.side_effect = client.HttpError(
            http_status=404)
        with self.assertRaises(ResourceNotFound) as e:
            self.mgr.get('ls')(paths=[fq_name])
            self.assertEqual("%s doesn't exists" % fq_name, str(e))
        self.assertFalse(mock_session.get_json.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_count(self, mock_session):
        mock_session.get_json.return_value = {'foos': {'count': 3}}

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('du')()
        self.assertEqual(result, '3')

        Context().shell.current_path = Path('/')
        result = self.mgr.get('du')(paths=['foo'])
        self.assertEqual(result, '3')

        Context().shell.current_path = Path('/foo/%s' % uuid.uuid4())
        with self.assertRaises(CommandError):
            self.mgr.get('du')()

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm(self, mock_continue_prompt, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/')
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ])
        self.assertFalse(mock_continue_prompt.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_rm_multiple_resources(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/foo')
        ts = [
            '6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
            '22916187-5b6f-40f1-b7b6-fc6fe9f23bce'
        ]
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=ts, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/22916187-5b6f-40f1-b7b6-fc6fe9f23bce'),
            mock.call(self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ])

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_rm_wildcard_resources(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/foo')
        mock_session.get_json.return_value = {
            'foos': [{
                'href':
                self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'fq_name': ['default', 'foo', '1']
            }, {
                'href':
                self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a',
                'fq_name': ['default', 'foo', '1']
            }]
        }
        mock_session.delete.return_value = True
        t = ['ec1afeaa-8930*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])
        t = ['*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])
        t = ['default:*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm_noconfirm(self, mock_continue_prompt, mock_session):
        Context().shell.current_path = Path('/')
        mock_continue_prompt.return_value = False
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        self.mgr.get('rm')(paths=t)
        self.assertFalse(mock_session.delete.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm_recursive(self, mock_continue_prompt, mock_session):
        Context().shell.current_path = Path('/')
        Collection('bar')
        Collection('foobar')
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        mock_continue_prompt.return_value = True
        mock_session.configure_mock(base_url=self.BASE)
        mock_session.get_json.side_effect = [{
            'foo': {
                'href':
                self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
                'uuid':
                '6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
                'bar_back_refs': [{
                    'href':
                    self.BASE + '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                    'uuid':
                    '22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                    'to': ['bar', '22916187-5b6f-40f1-b7b6-fc6fe9f23bce']
                }, {
                    'href':
                    self.BASE + '/bar/776bdf88-6283-4c4b-9392-93a857807307',
                    'uuid':
                    '776bdf88-6283-4c4b-9392-93a857807307',
                    'to': ['bar', '776bdf88-6283-4c4b-9392-93a857807307']
                }]
            }
        }, {
            'bar': {
                'href':
                self.BASE + '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                'uuid':
                '22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                'foobar_back_refs': [{
                    'href':
                    self.BASE + '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01',
                    'to': ['foobar', '1050223f-a230-4ed6-96f1-c332700c5e01'],
                    'uuid':
                    '1050223f-a230-4ed6-96f1-c332700c5e01'
                }]
            }
        }, {
            'foobar': {
                'href':
                self.BASE + '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01',
                'uuid': '1050223f-a230-4ed6-96f1-c332700c5e01'
            }
        }, {
            'bar': {
                'href':
                self.BASE + '/bar/776bdf88-6283-4c4b-9392-93a857807307',
                'uuid': '776bdf88-6283-4c4b-9392-93a857807307'
            }
        }]
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=t, recursive=True)
        expected_calls = [
            mock.call.delete(self.BASE +
                             '/bar/776bdf88-6283-4c4b-9392-93a857807307'),
            mock.call.delete(self.BASE +
                             '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01'),
            mock.call.delete(self.BASE +
                             '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce'),
            mock.call.delete(self.BASE +
                             '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ]
        mock_session.delete.assert_has_calls(expected_calls)

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.shell.prompt')
    def test_pipes(self, mock_prompt, mock_session):
        old_stdout = sys.stdout
        out = io.BytesIO()
        sys.stdout = out
        mock_prompt.side_effect = ["cmd | grep piped", "cmd", "exit"]
        self.mgr.get('shell')()
        sys.stdout = old_stdout
        result = out.getvalue()
        self.assertEqual(result, b'piped\nnot piped\n')

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.shell.prompt')
    def test_shell_args(self, mock_prompt, mock_session):
        old_stdout = sys.stdout
        out = io.BytesIO()
        sys.stdout = out
        mock_prompt.side_effect = ["arg-test \"foo  bar\"", "exit"]
        self.mgr.get('shell')()
        sys.stdout = old_stdout
        result = out.getvalue()
        self.assertEqual(result, b'foo  bar\n')

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_ln(self, mock_session):
        Context().schema = create_schema_from_version('2.21')
        r1 = Resource('virtual-network',
                      uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r2 = Resource('route-table',
                      uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r3 = Resource('project', uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r5 = Resource('logical-router',
                      uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        self.mgr.get('ln')(resources=[r1.path, r2.path])
        self.mgr.get('ln')(resources=[r1.path, r2.path], remove=True)
        self.mgr.get('ln')(resources=[r1.path, r5.path])
        self.mgr.get('ln')(resources=[r1.path, r5.path], remove=True)
        with self.assertRaises(CommandError):
            self.mgr.get('ln')(resources=[r1.path, r3.path])
        with self.assertRaises(CommandError):
            self.mgr.get('ln')(resources=[
                'foo/9174e7d3-865b-4faf-ab0f-c083e43fee6d', r1.path
            ])
        Context().schema = DummySchema()

    def test_schema(self):
        self.mgr.get('schema')(schema_version='2.21')
        self.mgr.get('schema')(schema_version='2.21',
                               resource_name='virtual-network')
        self.mgr.get('schema')(schema_version='2.21',
                               resource_name='route-target')
        with self.assertRaises(CommandError):
            self.mgr.get('schema')(schema_version='2.21', resource_name='foo')
        with self.assertRaises(CommandError):
            self.mgr.get('schema')(schema_version='4.0',
                                   resource_name='route-target')
        self.mgr.get('schema')(schema_version='4.0', list_version=True)
class TestCommand(CLITest):

    def setUp(self):
        CLITest.setUp(self)
        self.mgr = CommandManager()
        self.mgr.load_namespace('contrail_api_cli.shell_command')
        self.mgr.add('cmd', Cmd('cmd'))
        self.mgr.add('arg-test', ArgTest('arg-test'))

    def test_cd(self):
        self.mgr.get('cd')('foo')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('bar')
        self.assertEqual(Context().shell.current_path, Path('/foo/bar'))
        self.mgr.get('cd')('..')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('')
        self.assertEqual(Context().shell.current_path, Path('/foo'))
        self.mgr.get('cd')('/')
        self.assertEqual(Context().shell.current_path, Path('/'))

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_root_collection(self, mock_session):
        Context().shell.current_path = Path('/')
        mock_session.get_json.return_value = {
            'href': self.BASE,
            'links': [
                {'link': {'href': self.BASE + '/instance-ips',
                          'path': Path('/instance-ips'),
                          'name': 'instance-ip',
                          'rel': 'collection'}},
                {'link': {'href': self.BASE + '/instance-ip',
                          'path': Path('/instance-ip'),
                          'name': 'instance-ip',
                          'rel': 'resource-base'}}
            ]
        }
        result = self.mgr.get('ls')()
        self.assertEqual('instance-ip', result)

        mock_session.get_json.side_effect = [
            {
                'href': self.BASE,
                'links': [
                    {'link': {'href': self.BASE + '/foos',
                              'path': Path('/foos'),
                              'name': 'foo',
                              'rel': 'collection'}},
                    {'link': {'href': self.BASE + '/bars',
                              'path': Path('/bars'),
                              'name': 'bar',
                              'rel': 'collection'}}
                ]
            },
            {
                'foos': [
                    {'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                     'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724'},
                    {'href': self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                     'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a'}
                ]
            },
            {
                'bars': [
                    {'href': self.BASE + '/bar/ffe8de43-a141-4336-8d70-bf970813bbf7',
                     'uuid': 'ffe8de43-a141-4336-8d70-bf970813bbf7'}
                ]
            }
        ]

        Context().shell.current_path = Path('/')
        expected_result = """foo/ec1afeaa-8930-43b0-a60a-939f23a50724
foo/c2588045-d6fb-4f37-9f46-9451f653fb6a
bar/ffe8de43-a141-4336-8d70-bf970813bbf7"""
        result = self.mgr.get('ls')(paths=['*'])
        self.assertEqual(result, expected_result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_collection(self, mock_session):
        mock_session.get_json.return_value = {
            'foos': [
                {'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                 'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724'},
                {'href': self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                 'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a'}
            ]
        }

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('ls')()
        self.assertEqual('\n'.join(['ec1afeaa-8930-43b0-a60a-939f23a50724',
                                    'c2588045-d6fb-4f37-9f46-9451f653fb6a']),
                         result)

        Context().shell.current_path = Path('/')
        result = self.mgr.get('ls')(paths=['foo'])
        self.assertEqual('\n'.join(['foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                                    'foo/c2588045-d6fb-4f37-9f46-9451f653fb6a']),
                         result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_ls(self, mock_session):
        mock_session.get_json.return_value = {
            'foo': {
                'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
            }
        }
        Context().shell.current_path = Path('/foo')
        expected_result = 'ec1afeaa-8930-43b0-a60a-939f23a50724'
        result = self.mgr.get('ls')(paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'])
        self.assertEqual(result, expected_result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_long_ls(self, mock_session):
        mock_session.id_to_fqname.return_value = {
            'type': 'foo',
            'fq_name': FQName('default-project:foo:ec1afeaa-8930-43b0-a60a-939f23a50724')
        }
        mock_session.get_json.return_value = {
            'foo': {
                'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'fq_name': ['default-project', 'foo', 'ec1afeaa-8930-43b0-a60a-939f23a50724'],
                'prop': {
                    'foo': False,
                    'bar': [1, 2, 3]
                }
            }
        }
        Context().shell.current_path = Path('/')
        result = self.mgr.get('ls')(paths=['foo/ec1afeaa-8930-43b0-a60a-939f23a50724'],
                                    long=True)
        expected_result = "foo/ec1afeaa-8930-43b0-a60a-939f23a50724  default-project:foo:ec1afeaa-8930-43b0-a60a-939f23a50724"
        self.assertEqual(result, expected_result)

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('ls')(paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'],
                                    long=True, fields=['prop'])
        expected_results = ["ec1afeaa-8930-43b0-a60a-939f23a50724  foo=False|bar=1,2,3",
                            "ec1afeaa-8930-43b0-a60a-939f23a50724  bar=1,2,3|foo=False"]

        self.assertTrue(any([result == r for r in expected_results]))

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_parent_uuid_ls(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        self.mgr.get('ls')(paths=['foo'])
        mock_session.get_json.assert_called_with(self.BASE + '/foos')
        self.mgr.get('ls')(paths=['foo'], parent_uuid='1ad831be-3b21-4870-aadf-8efc2b0a480d')
        mock_session.get_json.assert_called_with(self.BASE + '/foos', parent_id='1ad831be-3b21-4870-aadf-8efc2b0a480d')

    @mock.patch('contrail_api_cli.commands.cat.highlight_json')
    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_resource_cat(self, mock_session, mock_highlight_json):
        # bind original method to mock_session
        mock_session.id_to_fqname = client.ContrailAPISession.id_to_fqname.__get__(mock_session)
        mock_session.make_url = client.ContrailAPISession.make_url.__get__(mock_session)

        # called by id_to_fqname
        def post(url, json=None):
            if json['uuid'] == "ec1afeaa-8930-43b0-a60a-939f23a50724":
                return {
                    "type": "foo",
                    "fq_name": [
                        "foo",
                        "ec1afeaa-8930-43b0-a60a-939f23a50724"
                    ]
                }
            if json['uuid'] == "15315402-8a21-4116-aeaa-b6a77dceb191":
                return {
                    "type": "bar",
                    "fq_name": [
                        "bar",
                        "15315402-8a21-4116-aeaa-b6a77dceb191"
                    ]
                }

        mock_session.post_json.side_effect = post
        mock_highlight_json.side_effect = lambda d: d
        mock_session.get_json.return_value = {
            'foo': {
                'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
                'attr': None,
                'fq_name': [
                    'foo',
                    'ec1afeaa-8930-43b0-a60a-939f23a50724'
                ],
                'bar_refs': [
                    {
                        'href': self.BASE + '/bar/15315402-8a21-4116-aeaa-b6a77dceb191',
                        'uuid': '15315402-8a21-4116-aeaa-b6a77dceb191',
                        'to': [
                            'bar',
                            '15315402-8a21-4116-aeaa-b6a77dceb191'
                        ]
                    }
                ]
            }
        }
        Context().shell.current_path = Path('/foo')
        expected_resource = Resource('foo', uuid='ec1afeaa-8930-43b0-a60a-939f23a50724',
                                     href=self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                                     attr=None, fq_name='foo:ec1afeaa-8930-43b0-a60a-939f23a50724')
        expected_resource['bar_refs'] = [
            Resource('bar', uuid='15315402-8a21-4116-aeaa-b6a77dceb191',
                     href=self.BASE + '/bar/15315402-8a21-4116-aeaa-b6a77dceb191',
                     to=['bar', '15315402-8a21-4116-aeaa-b6a77dceb191'])
        ]
        result = self.mgr.get('cat')(paths=['ec1afeaa-8930-43b0-a60a-939f23a50724'])
        self.assertEqual(expected_resource.json(), result)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_notfound_fqname_ls(self, mock_session):
        fq_name = 'default-domain:foo'
        Context().shell.current_path = Path('/foo')
        mock_session.fqname_to_id.side_effect = client.HttpError(http_status=404)
        with self.assertRaises(ResourceNotFound) as e:
            self.mgr.get('ls')(paths=[fq_name])
            self.assertEqual("%s doesn't exists" % fq_name, str(e))
        self.assertFalse(mock_session.get_json.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_count(self, mock_session):
        mock_session.get_json.return_value = {
            'foos': {
                'count': 3
            }
        }

        Context().shell.current_path = Path('/foo')
        result = self.mgr.get('du')()
        self.assertEqual(result, '3')

        Context().shell.current_path = Path('/')
        result = self.mgr.get('du')(paths=['foo'])
        self.assertEqual(result, '3')

        Context().shell.current_path = Path('/foo/%s' % uuid.uuid4())
        with self.assertRaises(CommandError):
            self.mgr.get('du')()

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm(self, mock_continue_prompt, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/')
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ])
        self.assertFalse(mock_continue_prompt.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_rm_multiple_resources(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/foo')
        ts = ['6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
              '22916187-5b6f-40f1-b7b6-fc6fe9f23bce']
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=ts, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/22916187-5b6f-40f1-b7b6-fc6fe9f23bce'),
            mock.call(self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ])

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_rm_wildcard_resources(self, mock_session):
        mock_session.configure_mock(base_url=self.BASE)
        Context().shell.current_path = Path('/foo')
        mock_session.get_json.return_value = {
            'foos': [
                {'href': self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724',
                 'uuid': 'ec1afeaa-8930-43b0-a60a-939f23a50724',
                 'fq_name': ['default', 'foo', '1']},
                {'href': self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a',
                 'uuid': 'c2588045-d6fb-4f37-9f46-9451f653fb6a',
                 'fq_name': ['default', 'foo', '1']}
            ]
        }
        mock_session.delete.return_value = True
        t = ['ec1afeaa-8930*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])
        t = ['*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])
        t = ['default:*', 'c2588045-d6fb-4f37-9f46-9451f653fb6a']
        self.mgr.get('rm')(paths=t, force=True)
        mock_session.delete.assert_has_calls([
            mock.call(self.BASE + '/foo/c2588045-d6fb-4f37-9f46-9451f653fb6a'),
            mock.call(self.BASE + '/foo/ec1afeaa-8930-43b0-a60a-939f23a50724')
        ])

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm_noconfirm(self, mock_continue_prompt, mock_session):
        Context().shell.current_path = Path('/')
        mock_continue_prompt.return_value = False
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        self.mgr.get('rm')(paths=t)
        self.assertFalse(mock_session.delete.called)

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.rm.continue_prompt')
    def test_rm_recursive(self, mock_continue_prompt, mock_session):
        Context().shell.current_path = Path('/')
        Collection('bar')
        Collection('foobar')
        t = ['foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f']
        mock_continue_prompt.return_value = True
        mock_session.configure_mock(base_url=self.BASE)
        mock_session.get_json.side_effect = [
            {
                'foo': {
                    'href': self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
                    'uuid': '6b6a7f47-807e-4c39-8ac6-3adcf2f5498f',
                    'bar_back_refs': [
                        {
                            'href': self.BASE + '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                            'uuid': '22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                            'to': [
                                'bar',
                                '22916187-5b6f-40f1-b7b6-fc6fe9f23bce'
                            ]
                        },
                        {
                            'href': self.BASE + '/bar/776bdf88-6283-4c4b-9392-93a857807307',
                            'uuid': '776bdf88-6283-4c4b-9392-93a857807307',
                            'to': [
                                'bar',
                                '776bdf88-6283-4c4b-9392-93a857807307'
                            ]
                        }
                    ]
                }
            },
            {
                'bar': {
                    'href': self.BASE + '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                    'uuid': '22916187-5b6f-40f1-b7b6-fc6fe9f23bce',
                    'foobar_back_refs': [
                        {
                            'href': self.BASE + '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01',
                            'to': [
                                'foobar',
                                '1050223f-a230-4ed6-96f1-c332700c5e01'
                            ],
                            'uuid': '1050223f-a230-4ed6-96f1-c332700c5e01'
                        }
                    ]
                }
            },
            {
                'foobar': {
                    'href': self.BASE + '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01',
                    'uuid': '1050223f-a230-4ed6-96f1-c332700c5e01'
                }
            },
            {
                'bar': {
                    'href': self.BASE + '/bar/776bdf88-6283-4c4b-9392-93a857807307',
                    'uuid': '776bdf88-6283-4c4b-9392-93a857807307'
                }
            }
        ]
        mock_session.delete.return_value = True
        self.mgr.get('rm')(paths=t, recursive=True)
        expected_calls = [
            mock.call.delete(self.BASE + '/bar/776bdf88-6283-4c4b-9392-93a857807307'),
            mock.call.delete(self.BASE + '/foobar/1050223f-a230-4ed6-96f1-c332700c5e01'),
            mock.call.delete(self.BASE + '/bar/22916187-5b6f-40f1-b7b6-fc6fe9f23bce'),
            mock.call.delete(self.BASE + '/foo/6b6a7f47-807e-4c39-8ac6-3adcf2f5498f')
        ]
        mock_session.delete.assert_has_calls(expected_calls)

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.shell.prompt')
    def test_pipes(self, mock_prompt, mock_session):
        old_stdout = sys.stdout
        out = io.BytesIO()
        sys.stdout = out
        mock_prompt.side_effect = [
            "cmd | grep piped",
            "cmd",
            "exit"
        ]
        self.mgr.get('shell')()
        sys.stdout = old_stdout
        result = out.getvalue()
        self.assertEqual(result, b'piped\nnot piped\n')

    @mock.patch('contrail_api_cli.resource.Context.session')
    @mock.patch('contrail_api_cli.commands.shell.prompt')
    def test_shell_args(self, mock_prompt, mock_session):
        old_stdout = sys.stdout
        out = io.BytesIO()
        sys.stdout = out
        mock_prompt.side_effect = [
            "arg-test \"foo  bar\"",
            "exit"
        ]
        self.mgr.get('shell')()
        sys.stdout = old_stdout
        result = out.getvalue()
        self.assertEqual(result, b'foo  bar\n')

    @mock.patch('contrail_api_cli.resource.Context.session')
    def test_ln(self, mock_session):
        Context().schema = create_schema_from_version('2.21')
        r1 = Resource('virtual-network', uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r2 = Resource('route-table', uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r3 = Resource('project', uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        r5 = Resource('logical-router', uuid='9174e7d3-865b-4faf-ab0f-c083e43fee6d')
        self.mgr.get('ln')(resources=[r1.path, r2.path])
        self.mgr.get('ln')(resources=[r1.path, r2.path], remove=True)
        self.mgr.get('ln')(resources=[r1.path, r5.path])
        self.mgr.get('ln')(resources=[r1.path, r5.path], remove=True)
        with self.assertRaises(CommandError):
            self.mgr.get('ln')(resources=[r1.path, r3.path])
        with self.assertRaises(CommandError):
            self.mgr.get('ln')(resources=['foo/9174e7d3-865b-4faf-ab0f-c083e43fee6d', r1.path])
        Context().schema = DummySchema()

    def test_schema(self):
        self.mgr.get('schema')(schema_version='2.21')
        self.mgr.get('schema')(schema_version='2.21', resource_name='virtual-network')
        self.mgr.get('schema')(schema_version='2.21', resource_name='route-target')
        with self.assertRaises(CommandError):
            self.mgr.get('schema')(schema_version='2.21', resource_name='foo')
        with self.assertRaises(CommandError):
            self.mgr.get('schema')(schema_version='4.0', resource_name='route-target')
        self.mgr.get('schema')(schema_version='4.0', list_version=True)