Skip to content

Commit

Permalink
Merge pull request #75 from dathelen/develop
Browse files Browse the repository at this point in the history
add banner support to system api
  • Loading branch information
devrobo committed Jan 25, 2016
2 parents 18e2455 + b8dcc75 commit 92f6fb5
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 6 deletions.
47 changes: 47 additions & 0 deletions pyeapi/api/system.py
Expand Up @@ -67,6 +67,8 @@ def get(self):
resource = dict()
resource.update(self._parse_hostname())
resource.update(self._parse_iprouting())
resource.update(self._parse_banners())

return resource

def _parse_hostname(self):
Expand All @@ -92,6 +94,27 @@ def _parse_iprouting(self):
value = 'no ip routing' not in self.config
return dict(iprouting=value)

def _parse_banners(self):
"""Parses the global config and returns the value for both motd
and login banners.
Returns:
dict: The configure value for modtd and login banners. If the
banner is not set it will return a value of None for that
key. The returned dict object is intendd to be merged
into the resource dict
"""
motd_value = login_value = None
matches = re.findall('^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n', self.config,
re.DOTALL | re.M)
for match in matches:
if match[0].strip() == "motd":
motd_value = match[1]
elif match[0].strip() == "login":
login_value = match[1]

return dict(banner_motd=motd_value, banner_login=login_value)

def set_hostname(self, value=None, default=False, disable=False):
"""Configures the global system hostname setting
Expand Down Expand Up @@ -130,7 +153,31 @@ def set_iprouting(self, value=None, default=False, disable=False):
cmd = self.command_builder('ip routing', value=value, default=default,
disable=disable)
return self.configure(cmd)

def set_banner(self, banner_type, value=None, default=False, disable=False):
"""Configures system banners
Args:
banner_type(str): banner to be changed (likely either login or motd)
value(str): value to set for the banner
default (bool): Controls the use of the default keyword
disable (bool): Controls the use of the no keyword`
Returns:
bool: True if the commands completed successfully otherwise False
"""

command_string = "banner %s" % banner_type
if default is True or disable is True:
cmd = self.command_builder(command_string, value=None, default=default,
disable=disable)
return self.configure(cmd)
else:
if not value.endswith("\n"):
value = value + "\n"
command_input = dict(cmd=command_string, input=value)
return self.configure([command_input])


def instance(api):
"""Returns an instance of System
Expand Down
5 changes: 3 additions & 2 deletions pyeapi/client.py
Expand Up @@ -500,7 +500,8 @@ def config(self, commands):
Args:
commands (str, list): The commands to send to the node in config
mode. If the commands argument is a string it will be cast to
a list. The list of commands will also be prepended with the
a list.
The list of commands will also be prepended with the
necessary commands to put the session in config mode.
Returns:
Expand All @@ -510,7 +511,7 @@ def config(self, commands):
"""
commands = make_iterable(commands)
commands = list(commands)

# push the configure command onto the command stack
commands.insert(0, 'configure terminal')
response = self.run_commands(commands)
Expand Down
4 changes: 4 additions & 0 deletions test/lib/testlib.py
Expand Up @@ -111,6 +111,10 @@ def eapi_exception_config_test(self, func, exc, *args, **kwargs):
with self.assertRaises(exc):
self.eapi_config_test(func, *args, **kwargs)

def eapi_positive_config_with_input_test(self, func, cmds=None,
*args, **kwargs):
result = self.eapi_config_test(func, cmds, *args, **kwargs)
self.assertTrue(result)



Expand Down
98 changes: 97 additions & 1 deletion test/system/test_api_system.py
Expand Up @@ -45,9 +45,10 @@ def test_get(self):
for dut in self.duts:
dut.config('default hostname')
resp = dut.api('system').get()
keys = ['hostname', 'iprouting']
keys = ['hostname', 'iprouting', 'banner_motd', 'banner_login']
self.assertEqual(sorted(keys), sorted(resp.keys()))


def test_get_with_period(self):
for dut in self.duts:
dut.config('hostname host.domain.net')
Expand All @@ -60,6 +61,23 @@ def test_get_check_hostname(self):
response = dut.api('system').get()
self.assertEqual(response['hostname'], 'teststring')

def test_get_check_banners(self):
for dut in self.duts:
motd_banner_value = random_string() + "\n"
login_banner_value = random_string() + "\n"
dut.config([dict(cmd="banner motd",input=motd_banner_value)])
dut.config([dict(cmd="banner login",input=login_banner_value)])
resp = dut.api('system').get()
self.assertEqual(resp['banner_login'], login_banner_value.rstrip())
self.assertEqual(resp['banner_motd'], motd_banner_value.rstrip())

def test_get_banner_with_EOF(self):
for dut in self.duts:
motd_banner_value = '!!!newlinebaner\n\nSecondLIneEOF!!!newlinebanner\n'
dut.config([dict(cmd="banner motd", input=motd_banner_value)])
resp = dut.api('system').get()
self.assertEqual(resp['banner_motd'], motd_banner_value.rstrip())

def test_set_hostname_with_value(self):
for dut in self.duts:
dut.config('default hostname')
Expand Down Expand Up @@ -129,6 +147,84 @@ def test_set_hostname_with_period(self):
value = 'hostname host.domain.net'
self.assertIn(value, dut.running_config)

def test_set_banner_motd(self):
for dut in self.duts:
banner_value = random_string()
dut.config([dict(cmd="banner motd",
input=banner_value)])
self.assertIn(banner_value, dut.running_config)
banner_api_value = random_string()
resp = dut.api('system').set_banner("motd", banner_api_value)
self.assertTrue(resp, 'dut=%s' % dut)
self.assertIn(banner_api_value, dut.running_config)

def test_set_banner_motd_donkey(self):
for dut in self.duts:
donkey_chicken = """
/\ /\
( \\ // )
\ \\ // /
\_\\||||//_/
\/ _ _ \
\/|(o)(O)|
\/ | |
___________________\/ \ /
// // |____| Cluck cluck cluck!
// || / \
//| \| \ 0 0 /
// \ ) V / \____/
// \ / ( /
"" \ /_________| |_/
/ /\ / | ||
/ / / / \ ||
| | | | | ||
| | | | | ||
|_| |_| |_||
\_\ \_\ \_\\
"""

resp = dut.api('system').set_banner("motd", donkey_chicken)
self.assertTrue(resp, 'dut=%s' % dut)
self.assertIn(donkey_chicken, dut.running_config)



def test_set_banner_motd_default(self):
for dut in self.duts:
dut.config([dict(cmd="banner motd",
input="!!!!REMOVE BANNER TEST!!!!")])
resp = dut.api('system').set_banner('motd', None, True)
self.assertIn('no banner motd', dut.running_config)

def test_set_banner_login(self):
for dut in self.duts:
banner_value = random_string()
dut.config([dict(cmd="banner login",
input=banner_value)])
self.assertIn(banner_value, dut.running_config)
banner_api_value = random_string()
resp = dut.api('system').set_banner("login", banner_api_value)
self.assertTrue(resp, 'dut=%s' % dut)
self.assertIn(banner_api_value, dut.running_config)
config_login_banner = dut.api('system').get()['banner_login']
self.assertTrue(config_login_banner, banner_api_value.strip())

def test_set_banner_login_default(self):
for dut in self.duts:
dut.config([dict(cmd="banner login",
input="!!!!REMOVE LOGIN BANNER TEST!!!!")])
resp = dut.api('system').set_banner('login', None, True)
self.assertIn('no banner login', dut.running_config)

def test_set_banner_login_negate(self):
for dut in self.duts:
dut.config([dict(cmd="banner login",
input="!!!!REMOVE LOGIN BANNER TEST!!!!")])
resp = dut.api('system').set_banner('login', None, False, True)
self.assertIn('no banner login', dut.running_config)




if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion test/unit/test_api_interfaces.py
Expand Up @@ -273,7 +273,7 @@ def test_get(self):
self.assertEqual(values, result)

def test_set_minimum_links_with_value(self):
minlinks = random_int(0, 16)
minlinks = random_int(1, 16)
cmds = ['interface Port-Channel1',
'port-channel min-links %s' % minlinks]
func = function('set_minimum_links', 'Port-Channel1', minlinks)
Expand Down
20 changes: 18 additions & 2 deletions test/unit/test_api_system.py
Expand Up @@ -48,9 +48,11 @@ def __init__(self, *args, **kwargs):
self.config = open(get_fixture('running_config.text')).read()

def test_get(self):
keys = ['hostname', 'iprouting']
keys = ['hostname', 'iprouting', 'banner_motd', 'banner_login']
result = self.instance.get()
self.assertEqual(sorted(keys), sorted(list(result.keys())))
self.assertIsNotNone(self.instance.get()['banner_motd'])
self.assertIsNotNone(self.instance.get()['banner_login'])

def test_set_hostname(self):
for state in ['config', 'negate', 'default']:
Expand Down Expand Up @@ -79,8 +81,22 @@ def test_set_iprouting(self):
func = function('set_iprouting', default=True)
self.eapi_positive_config_test(func, cmds)

def test_set_banner(self):
banner_value = random_string() + "\n"
func = function('set_banner', banner_type='motd',
value=banner_value)
cmds = [dict(cmd='banner motd', input=banner_value)]
self.eapi_positive_config_test(func, cmds)


def test_set_banner_default_disable(self):
func = function('set_banner', banner_type='motd',
value=None, default=True)
cmds = 'default banner motd'
self.eapi_positive_config_test(func, cmds)
func = function('set_banner', banner_type='motd',
value=None, disable=True)
cmds = 'no banner motd'
self.eapi_positive_config_test(func, cmds)

if __name__ == '__main__':
unittest.main()

0 comments on commit 92f6fb5

Please sign in to comment.