Skip to content

Commit

Permalink
Add profile clear command line and associated tests. Closes #38.
Browse files Browse the repository at this point in the history
  • Loading branch information
chambridge committed Sep 28, 2017
1 parent 97c146b commit cf69162
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 1 deletion.
3 changes: 2 additions & 1 deletion quipucords/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from cli.network.add import NetworkAddCommand
from cli.network.list import NetworkListCommand
from cli.network.show import NetworkShowCommand
from cli.network.clear import NetworkClearCommand
from . import __version__


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

Expand Down
92 changes: 92 additions & 0 deletions quipucords/cli/network/clear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/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.
#
""" NetworkClearCommand is used to clear specific network profile
or all network profiles
"""

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


# pylint: disable=too-few-public-methods
class NetworkClearCommand(CliCommand):
"""
This command is for clearing a specific network profile or all network
profiles.
"""
SUBCOMMAND = network.SUBCOMMAND
ACTION = network.CLEAR

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])
group = self.parser.add_mutually_exclusive_group(required=True)
group.add_argument('--name', dest='name', metavar='NAME',
help='profile name')
group.add_argument('--all', dest='all', action='store_true',
help='remove all network profiles')

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

def _delete_entry(self, profile_entry, print_out=True):
deleted = False
delete_uri = network.NETWORK_URI + str(profile_entry['id']) + '/'
response = request(DELETE, delete_uri, parser=self.parser)
name = profile_entry['name']
# pylint: disable=no-member
if response.status_code == codes.no_content:
deleted = True
if print_out:
print('Profile "%s" was removed' % name)
else:
handle_error_response(response)
if print_out:
print('Failed to remove profile "%s"' % name)
return deleted

def _handle_response_success(self):
json_data = self.response.json()
response_len = len(json_data)
if self.args.name and response_len == 0:
print('Profile "%s" was not found' % self.args.name)
sys.exit(1)
elif self.args.name and response_len == 1:
# delete single credential
entry = json_data[0]
if self._delete_entry(entry) is False:
sys.exit(1)
elif response_len == 0:
print("No profiles exist to be removed")
sys.exit(1)
else:
# remove all entries
remove_error = []
for entry in json_data:
if self._delete_entry(entry, print_out=False) is False:
remove_error.append(entry['name'])
if remove_error != []:
cred_err = ','.join(remove_error)
print('Some profiles were removed, however an error'
' occurred removing the following profiles: %s'
% cred_err)
sys.exit(1)
else:
print('All profiles were removed')
198 changes: 198 additions & 0 deletions quipucords/cli/network/tests_clear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#
# 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.clear import NetworkClearCommand

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


class NetworkClearCliTests(unittest.TestCase):
"""Class for testing the profile clear 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_clear_network_ssl_err(self):
"""Testing the clear 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)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
self.assertEqual(network_out.getvalue(), SSL_ERROR_MSG)

def test_clear_network_conn_err(self):
"""Testing the clear 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)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
self.assertEqual(network_out.getvalue(),
CONNECTION_ERROR_MSG)

def test_clear_network_internal_err(self):
"""Testing the clear 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']})
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
self.assertEqual(network_out.getvalue(), 'Server Error')

def test_clear_network_empty(self):
"""Testing the clear 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=[])
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
self.assertEqual(network_out.getvalue(),
'Profile "profile1" was not found\n')

def test_clear_by_name(self):
"""Testing the clear profile command successfully with stubbed data
when specifying a name
"""
network_out = StringIO()
get_url = BASE_URL + NETWORK_URI + '?name=profile1'
delete_url = BASE_URL + NETWORK_URI + '1/'
profile_entry = {'id': 1, 'name': 'profile1', 'hosts': ['1.2.3.4'],
'auth': ['auth1', 'auth2'], 'ssh_port': 22}
data = [profile_entry]
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=204)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with redirect_stdout(network_out):
ncc.main(args)
expected = 'Profile "profile1" was removed\n'
self.assertEqual(network_out.getvalue(), expected)

def test_clear_by_name_err(self):
"""Testing the clear profile command successfully with stubbed data
when specifying a name with an error response
"""
network_out = StringIO()
get_url = BASE_URL + NETWORK_URI + '?name=profile1'
delete_url = BASE_URL + NETWORK_URI + '1/'
profile_entry = {'id': 1, 'name': 'profile1', 'hosts': ['1.2.3.4'],
'auth': ['auth1', 'auth2'], 'ssh_port': 22}
data = [profile_entry]
err_data = {'error': ['Server Error']}
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)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name='profile1')
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
expected = 'Failed to remove profile "profile1"'
self.assertTrue(expected in network_out.getvalue())

def test_clear_all_empty(self):
"""Testing the clear profile command successfully with stubbed data
empty list of profiles
"""
network_out = StringIO()
get_url = BASE_URL + NETWORK_URI
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=[])
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name=None)
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
expected = 'No profiles exist to be removed\n'
self.assertEqual(network_out.getvalue(), expected)

def test_clear_all_with_error(self):
"""Testing the clear profile command successfully with stubbed data
a list of profiles with delete error
"""
network_out = StringIO()
get_url = BASE_URL + NETWORK_URI
delete_url = BASE_URL + NETWORK_URI + '1/'
profile_entry = {'id': 1, 'name': 'profile1', 'hosts': ['1.2.3.4'],
'auth': ['auth1', 'auth2'], 'ssh_port': 22}
data = [profile_entry]
err_data = {'error': ['Server Error']}
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)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name=None)
with self.assertRaises(SystemExit):
with redirect_stdout(network_out):
ncc.main(args)
expected = 'Some profiles were removed, however and' \
' error occurred removing the following' \
' credentials:'
self.assertTrue(expected in network_out.getvalue())

def test_clear_all(self):
"""Testing the clear profile command successfully with stubbed data
a list of profiles
"""
network_out = StringIO()
get_url = BASE_URL + NETWORK_URI
delete_url = BASE_URL + NETWORK_URI + '1/'
profile_entry = {'id': 1, 'name': 'profile1', 'hosts': ['1.2.3.4'],
'auth': ['auth1', 'auth2'], 'ssh_port': 22}
data = [profile_entry]
with requests_mock.Mocker() as mocker:
mocker.get(get_url, status_code=200, json=data)
mocker.delete(delete_url, status_code=204)
ncc = NetworkClearCommand(SUBPARSER)
args = Namespace(name=None)
with redirect_stdout(network_out):
ncc.main(args)
expected = 'All profiles were removed\n'
self.assertEqual(network_out.getvalue(), expected)

0 comments on commit cf69162

Please sign in to comment.