Skip to content

Commit

Permalink
Add profile show commands and associated test, plus some clean up. Cl…
Browse files Browse the repository at this point in the history
…oses #37. (#56)
  • Loading branch information
chambridge committed Sep 28, 2017
1 parent 943de56 commit 97c146b
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 28 deletions.
3 changes: 1 addition & 2 deletions quipucords/cli/auth/clear.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
# pylint: disable=too-few-public-methods
class AuthClearCommand(CliCommand):
"""
This command is for showing an auth which can be later associated with
profiles to gather facts.
This command is for clearing a specific credential or all credentials.
"""
SUBCOMMAND = auth.SUBCOMMAND
ACTION = auth.CLEAR
Expand Down
4 changes: 2 additions & 2 deletions quipucords/cli/auth/edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# along with this software; if not, see
# https://www.gnu.org/licenses/gpl-3.0.txt.
#
""" AuthAddCommand is used to add authentication credentials
""" AuthEditCommand is used to edit existing authentication credentials
for system access
"""

Expand Down Expand Up @@ -59,7 +59,7 @@ def _validate_args(self):

if not(self.args.username or self.args.password or
self.args.sudo_password or self.args.filename):
print('No arguments provided to edit for credential %s' %
print('No arguments provided to edit credential %s' %
(self.args.name))
self.parser.print_help()
sys.exit(1)
Expand Down
36 changes: 18 additions & 18 deletions quipucords/cli/auth/tests_clear.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ def test_clear_auth_ssl_err(self):
url = BASE_URL + AUTH_URI + '?name=auth1'
with requests_mock.Mocker() as mocker:
mocker.get(url, exc=requests.exceptions.SSLError)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
self.assertEqual(auth_out.getvalue(), SSL_ERROR_MSG)

def test_clear_auth_conn_err(self):
Expand All @@ -58,11 +58,11 @@ def test_clear_auth_conn_err(self):
url = BASE_URL + AUTH_URI + '?name=auth1'
with requests_mock.Mocker() as mocker:
mocker.get(url, exc=requests.exceptions.ConnectTimeout)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
self.assertEqual(auth_out.getvalue(), CONNECTION_ERROR_MSG)

def test_clear_auth_internal_err(self):
Expand All @@ -72,11 +72,11 @@ def test_clear_auth_internal_err(self):
url = BASE_URL + AUTH_URI + '?name=auth1'
with requests_mock.Mocker() as mocker:
mocker.get(url, status_code=500, json={'error': ['Server Error']})
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
self.assertEqual(auth_out.getvalue(), 'Server Error')

def test_clear_auth_empty(self):
Expand All @@ -86,11 +86,11 @@ def test_clear_auth_empty(self):
url = BASE_URL + AUTH_URI + '?name=auth1'
with requests_mock.Mocker() as mocker:
mocker.get(url, status_code=200, json=[])
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
self.assertEqual(auth_out.getvalue(),
'Auth "auth1" was not found\n')

Expand All @@ -107,10 +107,10 @@ def test_clear_by_name(self):
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=204)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
expected = 'Auth "auth1" was removed\n'
self.assertEqual(auth_out.getvalue(), expected)

Expand All @@ -128,11 +128,11 @@ def test_clear_by_name_err(self):
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=500, json=err_data)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name='auth1')
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
expected = 'Failed to remove credential "auth1"'
self.assertTrue(expected in auth_out.getvalue())

Expand All @@ -144,11 +144,11 @@ def test_clear_all_empty(self):
get_url = BASE_URL + AUTH_URI
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=[])
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name=None)
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
expected = 'No credentials exist to be removed\n'
self.assertEqual(auth_out.getvalue(), expected)

Expand All @@ -166,11 +166,11 @@ def test_clear_all_with_error(self):
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=500, json=err_data)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name=None)
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
expected = 'Some credentials were removed, however and' \
' error occurred removing the following' \
' credentials:'
Expand All @@ -189,9 +189,9 @@ def test_clear_all(self):
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=204)
asc = AuthClearCommand(SUBPARSER)
acc = AuthClearCommand(SUBPARSER)
args = Namespace(name=None)
with redirect_stdout(auth_out):
asc.main(args)
acc.main(args)
expected = 'All credentials were removed\n'
self.assertEqual(auth_out.getvalue(), expected)
10 changes: 5 additions & 5 deletions quipucords/cli/auth/tests_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@ def tearDown(self):
os.remove(TMP_KEY)

def test_edit_req_args_err(self):
"""Testing the add edit command required flags"""
"""Testing the auth edit command required flags"""
auth_out = StringIO()
with self.assertRaises(SystemExit):
with redirect_stdout(auth_out):
sys.argv = ['/bin/qpc', 'auth', 'edit', '--name', 'auth1']
CLI().main()
self.assertEqual(auth_out.getvalue(),
'No arguments provided to edit for '
'No arguments provided to edit '
'credential auth1')

def test_edit_bad_key(self):
"""Testing the add edit command when providing an invalid path for
"""Testing the auth edit command when providing an invalid path for
the sshkeyfile.
"""
auth_out = StringIO()
Expand Down Expand Up @@ -86,10 +86,10 @@ def test_edit_auth_none(self):
with redirect_stdout(auth_out):
aec.main(args)
aec.main(args)
self.assertTrue('credential with this name already exists.'
self.assertTrue('Auth "auth_none" does not exist'
in auth_out.getvalue())

def test_add_edit_ssl_err(self):
def test_edit_auth_ssl_err(self):
"""Testing the edit auth command with a connection error
"""
auth_out = StringIO()
Expand Down
4 changes: 3 additions & 1 deletion quipucords/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from cli.auth.clear import AuthClearCommand
from cli.network.add import NetworkAddCommand
from cli.network.list import NetworkListCommand
from cli.network.show import NetworkShowCommand
from . import __version__


Expand Down Expand Up @@ -52,7 +53,8 @@ def __init__(self, name="cli", usage=None, shortdesc=None,
AuthEditCommand, AuthShowCommand,
AuthClearCommand])
self._add_subcommand(network.SUBCOMMAND,
[NetworkAddCommand, NetworkListCommand])
[NetworkAddCommand, NetworkListCommand,
NetworkShowCommand])
ensure_data_dir_exists()
ensure_config_dir_exists()

Expand Down
53 changes: 53 additions & 0 deletions quipucords/cli/network/show.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 3 (GPLv3). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
# along with this software; if not, see
# https://www.gnu.org/licenses/gpl-3.0.txt.
#
""" NetworkShowCommand is used to show info on a specific network profiles
for system scans
"""

from __future__ import print_function
import sys
from requests import codes
from cli.utils import pretty_print
from cli.clicommand import CliCommand
import cli.network as network
from cli.request import GET


# pylint: disable=too-few-public-methods
class NetworkShowCommand(CliCommand):
"""
This command is for showing a network which can later be used with a scan
to gather facts.
"""
SUBCOMMAND = network.SUBCOMMAND
ACTION = network.SHOW

def __init__(self, subparsers):
# pylint: disable=no-member
CliCommand.__init__(self, self.SUBCOMMAND, self.ACTION,
subparsers.add_parser(self.ACTION), GET,
network.NETWORK_URI, [codes.ok])
self.parser.add_argument('--name', dest='name', metavar='NAME',
help='profile name', required=True)

def _build_req_params(self):
self.req_params = {'name': self.args.name}

def _handle_response_success(self):
json_data = self.response.json()
if len(json_data) == 1:
cred_entry = json_data[0]
data = pretty_print(cred_entry)
print(data)
else:
print('Profile "%s" does not exist' % self.args.name)
sys.exit(1)
115 changes: 115 additions & 0 deletions quipucords/cli/network/tests_show.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 3 (GPLv3). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
# along with this software; if not, see
# https://www.gnu.org/licenses/gpl-3.0.txt.
#
"""Test the CLI module"""

import unittest
import sys
from io import StringIO
from argparse import ArgumentParser, Namespace
import requests
import requests_mock
from cli.tests_utilities import HushUpStderr, redirect_stdout
from cli.request import BASE_URL, CONNECTION_ERROR_MSG, SSL_ERROR_MSG
from cli.network import NETWORK_URI
from cli.network.show import NetworkShowCommand

PARSER = ArgumentParser()
SUBPARSER = PARSER.add_subparsers(dest='subcommand')


class NetworkShowCliTests(unittest.TestCase):
"""Class for testing the profile show commands for qpc"""
def setUp(self):
# Temporarily disable stderr for these tests, CLI errors clutter up
# nosetests command.
self.orig_stderr = sys.stderr
sys.stderr = HushUpStderr()

def tearDown(self):
# Restore stderr
sys.stderr = self.orig_stderr

def test_show_network_ssl_err(self):
"""Testing the show profile command with a connection error
"""
network_out = StringIO()
url = BASE_URL + NETWORK_URI + '?name=profile1'
with requests_mock.Mocker() as mocker:
mocker.get(url, exc=requests.exceptions.SSLError)
nsc = NetworkShowCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
nsc.main(args)
self.assertEqual(network_out.getvalue(), SSL_ERROR_MSG)

def test_show_network_conn_err(self):
"""Testing the show profile command with a connection error
"""
network_out = StringIO()
url = BASE_URL + NETWORK_URI + '?name=profile1'
with requests_mock.Mocker() as mocker:
mocker.get(url, exc=requests.exceptions.ConnectTimeout)
nsc = NetworkShowCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
nsc.main(args)
self.assertEqual(network_out.getvalue(),
CONNECTION_ERROR_MSG)

def test_show_network_internal_err(self):
"""Testing the show profile command with an internal error
"""
network_out = StringIO()
url = BASE_URL + NETWORK_URI + '?name=profile1'
with requests_mock.Mocker() as mocker:
mocker.get(url, status_code=500, json={'error': ['Server Error']})
nsc = NetworkShowCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
nsc.main(args)
self.assertEqual(network_out.getvalue(), 'Server Error')

def test_show_network_empty(self):
"""Testing the show profile command successfully with empty data
"""
network_out = StringIO()
url = BASE_URL + NETWORK_URI + '?name=profile1'
with requests_mock.Mocker() as mocker:
mocker.get(url, status_code=200, json=[])
nsc = NetworkShowCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
nsc.main(args)
self.assertEqual(network_out.getvalue(),
'Profile "profile1" does not exist\n')

def test_show_network_data(self):
"""Testing the show profile command successfully with stubbed data
"""
network_out = StringIO()
url = BASE_URL + NETWORK_URI + '?name=profile1'
auth_entry = {'id': 1, 'name': 'profile1', 'hosts': ['1.2.3.4'],
'credentials': [{'id': 1, 'name': 'auth1'}]}
data = [auth_entry]
with requests_mock.Mocker() as mocker:
mocker.get(url, status_code=200, json=data)
nsc = NetworkShowCommand(SUBPARSER)
args = Namespace(name='profile1')
with redirect_stdout(network_out):
nsc.main(args)
expected = '{"credentials":[{"id":1,"name":"auth1"}],' \
'"hosts":["1.2.3.4"],"id":1,"name":"profile1"}'
self.assertEqual(network_out.getvalue().replace('\n', '')
.replace(' ', '').strip(), expected)

0 comments on commit 97c146b

Please sign in to comment.