2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 23:45:27 +00:00

[5137] A few fixes and many python style improvements

This commit is contained in:
Francis Dupont
2017-03-09 01:17:03 +01:00
parent b0d88c7da3
commit f0494b2149
12 changed files with 373 additions and 302 deletions

View File

@@ -470,7 +470,10 @@ AC_ARG_ENABLE(shell, [AC_HELP_STRING([--enable-shell],
if test "x$enable_shell" != xno ; then if test "x$enable_shell" != xno ; then
# If kea-shell is enabled, we really need python. 2.7 or anything newer will do. # If kea-shell is enabled, we really need python. 2.7 or anything newer will do.
AM_PATH_PYTHON([2.7]) AM_PATH_PYTHON([3], [found="yes"], [found="no"])
if test "x$found" = xno ; then
AM_PATH_PYTHON([2.7])
fi
else else
PYTHON=no PYTHON=no
fi fi
@@ -1628,8 +1631,10 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/bin/admin/tests/cql_tests.sh src/bin/admin/tests/cql_tests.sh
src/bin/agent/tests/test_libraries.h src/bin/agent/tests/test_libraries.h
src/bin/shell/Makefile src/bin/shell/Makefile
src/bin/shell/kea-shell
src/bin/shell/tests/Makefile src/bin/shell/tests/Makefile
src/bin/shell/tests/shell_process_tests.sh src/bin/shell/tests/shell_process_tests.sh
src/bin/shell/tests/shell_unittest.py
src/hooks/Makefile src/hooks/Makefile
src/hooks/dhcp/Makefile src/hooks/dhcp/Makefile
src/hooks/dhcp/user_chk/Makefile src/hooks/dhcp/user_chk/Makefile
@@ -1720,11 +1725,14 @@ AC_CONFIG_FILES([compatcheck/Makefile
]) ])
AC_CONFIG_COMMANDS([permissions], [ AC_CONFIG_COMMANDS([permissions], [
chmod +x src/bin/admin/kea-admin
chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh
chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh
chmod +x src/bin/keactrl/keactrl chmod +x src/bin/keactrl/keactrl
chmod +x src/bin/keactrl/tests/keactrl_tests.sh chmod +x src/bin/keactrl/tests/keactrl_tests.sh
chmod +x src/bin/admin/kea-admin chmod +x src/bin/shell/kea-shell
chmod +x src/bin/shell/tests/shell_process_tests.sh
chmod +x src/bin/shell/tests/shell_unittest.py
chmod +x src/lib/dns/gen-rdatacode.py chmod +x src/lib/dns/gen-rdatacode.py
chmod +x src/lib/log/tests/console_test.sh chmod +x src/lib/log/tests/console_test.sh
chmod +x src/lib/log/tests/destination_test.sh chmod +x src/lib/log/tests/destination_test.sh
@@ -1800,6 +1808,7 @@ if test "$PYTHON" != "no" ; then
cat >> config.report << END cat >> config.report << END
Python: Python:
PYTHON: ${PYTHON}
PYTHON_VERSION: ${PYTHON_VERSION} PYTHON_VERSION: ${PYTHON_VERSION}
END END

View File

@@ -5,7 +5,6 @@ SHTESTS += ca_process_tests.sh
noinst_SCRIPTS = ca_process_tests.sh noinst_SCRIPTS = ca_process_tests.sh
EXTRA_DIST = ca_process_tests.sh.in EXTRA_DIST = ca_process_tests.sh.in
noinst_LTLIBRARIES = libbasic.la
# test using command-line arguments, so use check-local target instead of TESTS # test using command-line arguments, so use check-local target instead of TESTS
check-local: check-local:
@@ -40,6 +39,8 @@ TESTS_ENVIRONMENT = \
TESTS = TESTS =
if HAVE_GTEST if HAVE_GTEST
noinst_LTLIBRARIES = libbasic.la
TESTS += ca_unittests TESTS += ca_unittests
ca_unittests_SOURCES = ca_cfg_mgr_unittests.cc ca_unittests_SOURCES = ca_cfg_mgr_unittests.cc

View File

@@ -5,7 +5,7 @@ EXTRA_DIST =
if KEA_SHELL if KEA_SHELL
# Kea-shell is enabled, here are proper rules for it. # Kea-shell is enabled, here are proper rules for it.
kea_shell_PYTHON = kea-shell.py kea_conn.py kea_connector2.py kea_connector3.py kea_shell_PYTHON = kea_conn.py kea_connector2.py kea_connector3.py
kea_shelldir = @localstatedir@/@PACKAGE@ kea_shelldir = @localstatedir@/@PACKAGE@
bin_SCRIPTS = kea-shell bin_SCRIPTS = kea-shell
@@ -13,12 +13,11 @@ bin_SCRIPTS = kea-shell
else else
# Kea-shell is disabled, simply keep the files for make dist # Kea-shell is disabled, simply keep the files for make dist
EXTRA_DIST += kea-shell.py kea_conn.py kea_connector2.py kea_connector3.py EXTRA_DIST += kea-shell kea_conn.py kea_connector2.py kea_connector3.py
endif endif
CLEANFILES = kea-shell kea-shell.pyc CLEANFILES = *.pyc
man_MANS = kea-shell.8 man_MANS = kea-shell.8
DISTCLEANFILES = $(man_MANS) DISTCLEANFILES = $(man_MANS)
@@ -38,13 +37,6 @@ $(man_MANS):
endif endif
# This is done here since configure.ac AC_OUTPUT doesn't expand certain variables.
kea-shell: kea-shell.py
$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" kea-shell.py > kea-shell.tmp
$(SED) "s|REPORTED_VERSION|@PACKAGE_VERSION@|" kea-shell.tmp >$@
rm -f kea-shell.tmp
chmod a+x $@
install-data-local: install-data-local:
$(mkinstalldirs) $(DESTDIR)/@localstatedir@/@PACKAGE@ $(mkinstalldirs) $(DESTDIR)/@localstatedir@/@PACKAGE@

112
src/bin/shell/kea-shell.in Normal file
View File

@@ -0,0 +1,112 @@
#!@PYTHON@
# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
Text client for Control Agent process
"""
# First, let's import the right kea_connector.
# We have two versions: one for python 2.x and another for python 3.x.
# Sadly, there's no unified way to handle http connections. The recommended
# way is to use Requests (http://docs.python-requests.org/en/master/), but
# that's a stand alone package that requires separate installation. One of
# the design requirements was to not require any additional packages, so
# the code uses standard libraries available in python. Hence two versions.
import sys
import signal
import argparse
from kea_conn import CARequest # CAResponse
if sys.version_info[0] == 2:
# This is Python 2.x
import kea_connector2 as kea_connector
elif sys.version_info[0] == 3:
# This is Python 3.x
import kea_connector3 as kea_connector
else:
# This is... have no idea what it is.
raise SystemExit("Unknown python version:" + str(sys.version_info[0]))
def timeout_handler(signum, frame):
"""Connection timeoout handler"""
del signum, frame
print("Connection timeout")
sys.exit(1)
VERSION = "@PACKAGE_VERSION@"
def shell_body():
"""
Second step: Need to parse command line parameters. We will use
argparse for that purpose. It does great job with having default
values, taking care of the help and sanity checking input
parameters.
"""
parser = argparse.ArgumentParser(description='kea-shell is a simple text '
'client that uses REST interface to '
'connect to Kea Control Agent.')
parser.add_argument('--host', type=str, default='127.0.0.1',
help='hostname of the CA to connect to '
'(defaul:; 127.0.0.1)')
parser.add_argument('--port', type=int, default=8000,
help='TCP port of the CA to connect to '
'(default: 8000)')
parser.add_argument('--timeout', type=int, default='10',
help='Timeout (in seconds) when attempting to '
'connect to CA (default: 10)')
parser.add_argument('command', type=str, nargs="?",
default='list-commands',
help='command to be executed. If not specified, '
'"list-commands" is used')
parser.add_argument('-v', action="store_true", help="Prints version")
cmd_args = parser.parse_args()
if cmd_args.v:
print(VERSION)
exit(0)
# Ok, now time to put the parameters parsed into the structure to be
# used by the connection.
params = CARequest()
params.command = cmd_args.command
params.http_host = cmd_args.host
params.http_port = cmd_args.port
params.timeout = cmd_args.timeout
params.version = VERSION
params.generate_body()
params.generate_headers()
# Load command processor
# @todo - command specific processing will be added as part of
# future work (either #5138 or #5139, whichever is implemented
# first)
# Read parameters from stdin (they're optional for some commands)
for line in sys.stdin:
params.params += line
# Set the timeout timer. If the connection takes too long,
# it will send a signal to us.
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(params.timeout)
# Ok, everything is ready. Let's send the command and get a response.
try:
resp = kea_connector.send_to_control_agent(params)
except Exception as exc:
print("Failed to run: " + str(exc))
sys.exit(1)
resp.print_response()
sys.exit(0)
if __name__ == "__main__":
shell_body()

View File

@@ -1,92 +0,0 @@
#!/usr/bin/python
# This is going to be replaced with the actual version (see kea-shell target
# in Makefile.am)
VERSION = "REPORTED_VERSION"
# First, let's import the right kea_connector.
# We have two versions: one for python 2.x and another for python 3.x.
# Sadly, there's no unified way to handle http connections. The recommended
# way is to use Requests (http://docs.python-requests.org/en/master/), but
# that's a stand alone package that requires separate installation. One of
# the design requirements was to not require any additional packages, so
# the code uses standard libraries available in python. Hence two versions.
import sys
import signal
import argparse
if (sys.version_info[0] == 2):
# This is Python 2.x
import kea_connector2 as kea_connector
else:
if (sys.version_info[0] == 3):
# This is Python 3.x
import kea_connector3 as kea_connector
else:
# This is... have no idea what it is.
raise SystemExit("Unknown python version:" + str(sys.version_info[0]))
from kea_conn import CARequest, CAResponse
# Second step: Need to parse command line parameters. We will use argparse for
# that purpose. It does great job with having default values, taking care of
# the help and sanity checking input parameters.
parser = argparse.ArgumentParser(description='kea-shell is a simple text client that uses REST '
'interface to connect to Kea Control Agent.')
parser.add_argument('--host', type=str, default='127.0.0.1',
help='hostname of the CA to connect to (default; 127.0.0.1)')
parser.add_argument('--port', type=int, default=8000,
help='TCP port of the CA to connect to (default: 8000)')
parser.add_argument('--timeout', type=int, default='10',
help='Timeout (in seconds) when attempting to connect to CA (default: 10)')
parser.add_argument('command', type=str, nargs="?", default='list-commands',
help='command to be executed. If not specified, "list-commands" is used')
parser.add_argument('-v', action="store_true", help="Prints version")
cmd_args = parser.parse_args()
if (cmd_args.v):
print (VERSION)
exit(0)
# Ok, now time to put the parameters parsed into the structure to be used by the
# connection.
params = CARequest()
params.command = cmd_args.command
params.http_host = cmd_args.host
params.http_port = cmd_args.port
params.timeout = cmd_args.timeout
params.version = VERSION
params.generateBody()
params.generateHeaders()
conn = kea_connector.KeaConnector()
def timeout_handler(signum, frame):
print ("Connection timeout")
sys.exit(1)
# Load command processor
# @todo - command specific processing will be added as part of future work
# (either #5138 or #5139, whichever is implemented first)
# Read parameters from stdin (they're optional for some commands)
for line in sys.stdin:
params.params += line
# Set the timeout timer. If the connection takes too long,
# it will send a signal to us.
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(params.timeout)
# Ok, everything is ready. Let's send the command and get a response.
try:
resp = conn.sendCA(params)
except Exception as e:
print("Failed to run: " + str(e))
sys.exit(1)
resp.printResp()
sys.exit(0)

View File

@@ -49,9 +49,10 @@
<cmdsynopsis> <cmdsynopsis>
<command>kea-shell</command> <command>kea-shell</command>
<arg><option>-h</option></arg> <arg><option>-h</option></arg>
<arg><option>-v</option></arg>
<arg><option>--host</option></arg> <arg><option>--host</option></arg>
<arg><option>--port</option></arg> <arg><option>--port</option></arg>
<arg><option>-v</option></arg> <arg><option>--timeout</option></arg>
<arg><option>command</option></arg> <arg><option>command</option></arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -64,8 +65,8 @@
Kea Control Agent (CA). It takes command as a command-line parameter Kea Control Agent (CA). It takes command as a command-line parameter
that is being sent to CA with proper JSON that is being sent to CA with proper JSON
encapsulation. Optional parameters may be specified on the encapsulation. Optional parameters may be specified on the
stdin. The request it sent of HTTP and a response is standard input. The request it sent of HTTP and a response is
retrieved. That response is printed out on stdout. retrieved. That response is displayed out on the standard output.
</para> </para>
</refsect1> </refsect1>
@@ -78,16 +79,16 @@
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><option>-v</option></term> <term><option>-h</option></term>
<listitem><para> <listitem><para>
Display the version. Displays help regarding command line parameters.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>-h</option></term> <term><option>-v</option></term>
<listitem><para> <listitem><para>
Displays help regarding command line parameters. Display the version.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>

View File

@@ -1,17 +1,25 @@
#!/usr/bin/python # Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This file contains classes used for communication with Control Agent. """
This file contains classes used for communication with Control Agent.
"""
# This class defines the HTTP request to be sent.
# The supported parameters listed are:
# - path (specifies the path on the server, CA uses only /)
# - http_host - hostname of the CA
# - http-port - TCP port of the CA
# - command - specifies the command to send (e.g. list-commands)
# - timeout - timeout (in ms)
# - headers - extra HTTP headers may be added here
# - version - version to be reported in HTTP header
class CARequest: class CARequest:
"""
This class defines the HTTP request to be sent.
The supported parameters listed are:
- path (specifies the path on the server, CA uses only /)
- http_host - hostname of the CA
- http-port - TCP port of the CA
- command - specifies the command to send (e.g. list-commands)
- timeout - timeout (in ms)
- headers - extra HTTP headers may be added here
- version - version to be reported in HTTP header
"""
path = '/' path = '/'
http_host = '' http_host = ''
http_port = 0 http_port = 0
@@ -20,39 +28,47 @@ class CARequest:
params = '' params = ''
headers = {} headers = {}
version = "" version = ""
# This is a storage for generated command (input data to be sent over POST)
content = ''
# Generates the content, out of specified command line def generate_body(self):
# and optional content. """
# @todo: Add support for parameters Generates the content, out of specified command line
# this stores the output in self.content and optional content.
def generateBody(self): @todo: Add support for parameters
this stores the output in self.content
"""
self.content = '{ "command": "' + self.command + '"' self.content = '{ "command": "' + self.command + '"'
if (len(self.params)): if len(self.params):
self.content += ', "parameters": { ' + self.params + ' }' self.content += ', "parameters": { ' + self.params + ' }'
self.content += ' }' self.content += ' }'
# Generate HTTP headers def generate_headers(self):
# """
# In particular, this method generates Content-Length and its value. Generate HTTP headers
def generateHeaders(self):
In particular, this method generates Content-Length and its value.
"""
self.headers['Content-Type'] = 'application/json' self.headers['Content-Type'] = 'application/json'
self.headers['User-Agent'] = "Kea-shell/%s"%(self.version) self.headers['User-Agent'] = "Kea-shell/%s"%(self.version)
self.headers['Accept'] = '*/*' self.headers['Accept'] = '*/*'
self.headers['Content-Length'] = "%d"%(len(self.content)) self.headers['Content-Length'] = "%d"%(len(self.content))
# This is a storage for generated command (input data to be sent over POST)
content = ''
# This class represents the HTTP response
class CAResponse: class CAResponse:
"""
This class represents the HTTP response
"""
# Constructor
#
# Three mandatory parameters are:
# status - numerical number the describe the status (e.g. 200 = OK)
# reason - textual explanation of what happened
# body - the actual body structure of the response
def __init__(self, status, reason, body): def __init__(self, status, reason, body):
"""
Constructor
Three mandatory parameters are:
status - numerical number the describe the status (e.g. 200 = OK)
reason - textual explanation of what happened
body - the actual body structure of the response
"""
self.status = status self.status = status
self.reason = reason self.reason = reason
self.body = body self.body = body
@@ -61,11 +77,13 @@ class CAResponse:
reason = '' reason = ''
body = '' body = ''
# Used for debugging def print_response(self, debug=False):
# """
# if defug is true, this prints even more information Used for debugging
def printResp(self, debug = False):
if (debug): if debug is true, this prints even more information
"""
if debug:
print(self.status) print(self.status)
print(self.reason) print(self.reason)
print(self.body) print(self.body)

View File

@@ -1,34 +1,39 @@
#!/usr/bin/python # Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This is PYTHON 2.x version of HTTP connection establishment """
This is PYTHON 2.x version of HTTP connection establishment
from kea_conn import CARequest, CAResponse """
import httplib import httplib
class KeaConnector: from kea_conn import CAResponse # CARequest
def sendCA(self, params):
# Estalbish HTTP connection first.
conn = httplib.HTTPConnection(params.http_host, params.http_port)
conn.connect()
# Use POST to send it def send_to_control_agent(params):
request = conn.putrequest('POST', params.path) """Establish HTTP connection first."""
conn = httplib.HTTPConnection(params.http_host, params.http_port)
conn.connect()
# Send the headers first # Use POST to send it
for k in params.headers: _ = conn.putrequest('POST', params.path)
conn.putheader(k, params.headers[k])
conn.endheaders()
# Send the content # Send the headers first
conn.send(params.content) for k in params.headers:
conn.putheader(k, params.headers[k])
conn.endheaders()
# Now get the response # Send the content
resp = conn.getresponse() conn.send(params.content)
# Now get the response details, put it in CAResponse and # Now get the response
# return it resp = conn.getresponse()
x = CAResponse(resp.status, resp.reason, resp.read())
conn.close()
return (x) # Now get the response details, put it in CAResponse and
# return it
result = CAResponse(resp.status, resp.reason, resp.read())
conn.close()
return result

View File

@@ -1,20 +1,29 @@
#!/usr/bin/python # Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from kea_conn import CARequest, CAResponse """
This is PYTHON 3.x version of HTTP connection establishment
"""
import urllib.request import urllib.request
class KeaConnector: from kea_conn import CAResponse # CARequest
def sendCA(self, params):
# Estalbish HTTP connection first.
url = "http://" + params.http_host + ":" + str(params.http_port) + str(params.path)
req = urllib.request.Request(url = url, data = str.encode(params.content),
headers = params.headers)
resp = urllib.request.urlopen(req)
# Now get the response details, put it in CAResponse and def send_to_control_agent(params):
# return it """Establish HTTP connection first."""
x = CAResponse(resp.getcode(), resp.reason, resp.read().decode("utf-8")) url = "http://" + params.http_host + ":"
url += str(params.http_port) + str(params.path)
return (x) req = urllib.request.Request(url=url,
data=str.encode(params.content),
headers=params.headers)
resp = urllib.request.urlopen(req)
# Now get the response details, put it in CAResponse and return it
result = CAResponse(resp.getcode(), resp.reason,
resp.read().decode("utf-8"))
return result

View File

@@ -36,8 +36,8 @@ CONFIG="{
}" }"
# In these tests we need to use two binaries: Control Agent and Kea shell. # In these tests we need to use two binaries: Control Agent and Kea shell.
# Using bin and bin_path would be confusing, so we omit defining bin and bin_path # Using bin and bin_path would be confusing, so we omit defining bin
# on purpose. # and bin_path on purpose.
ca_bin="kea-ctrl-agent" ca_bin="kea-ctrl-agent"
ca_bin_path=@abs_top_builddir@/src/bin/agent ca_bin_path=@abs_top_builddir@/src/bin/agent
@@ -83,8 +83,8 @@ shell_command_test() {
# of configuration failure). # of configuration failure).
get_pid ${ca_bin} get_pid ${ca_bin}
if [ ${_GET_PIDS_NUM} -ne 1 ]; then if [ ${_GET_PIDS_NUM} -ne 1 ]; then
printf "ERROR: expected one Control Agent process to be started. Found %d processes\ printf "ERROR: expected one Control Agent process to be started.\
started.\n" ${_GET_PIDS_NUM} Found %d processes started.\n" ${_GET_PIDS_NUM}
clean_exit 1 clean_exit 1
fi fi
@@ -92,22 +92,26 @@ shell_command_test() {
# It should be just once on startup. # It should be just once on startup.
get_reconfigs get_reconfigs
if [ ${_GET_RECONFIGS} -ne 1 ]; then if [ ${_GET_RECONFIGS} -ne 1 ]; then
printf "ERROR: server been configured ${_GET_RECONFIGS} time(s), but exactly 1 was expected.\n" printf "ERROR: server been configured ${_GET_RECONFIGS} time(s),\
but exactly 1 was expected.\n"
clean_exit 1 clean_exit 1
else else
printf "Server successfully configured.\n" printf "Server successfully configured.\n"
fi fi
# Main test phase: send command, check response. # Main test phase: send command, check response.
tmp="echo \"${params}\" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt" tmp="echo \"${params}\" | ${shell_bin_path}/${shell_bin} --host \
127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt"
echo "Executing kea-shell ($tmp)" echo "Executing kea-shell ($tmp)"
echo "${params}" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt echo "${params}" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 \
--port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt
# Check the exit code # Check the exit code
shell_exit_code=$? shell_exit_code=$?
if [ ${shell_exit_code} -ne 0 ]; then if [ ${shell_exit_code} -ne 0 ]; then
echo "ERROR: kea-shell returned ${shell_exit_code} exit code, expected 0." echo "ERROR:" \
"kea-shell returned ${shell_exit_code} exit code, expected 0."
else else
echo "kea-shell returned ${shell_exit_code} exit code as expected." echo "kea-shell returned ${shell_exit_code} exit code as expected."
fi fi
@@ -118,7 +122,9 @@ shell_command_test() {
diff ${tmpfile_path}/shell-stdout.txt ${tmpfile_path}/shell-expected.txt diff ${tmpfile_path}/shell-stdout.txt ${tmpfile_path}/shell-expected.txt
diff_code=$? diff_code=$?
if [ ${diff_code} -ne 0 ]; then if [ ${diff_code} -ne 0 ]; then
echo "ERROR: content returned is different than expected. See ${tmpfile_path}/shell-*.txt" echo "ERROR:" \
"content returned is different than expected." \
"See ${tmpfile_path}/shell-*.txt"
echo "EXPECTED:" echo "EXPECTED:"
cat ${tmpfile_path}/shell-expected.txt cat ${tmpfile_path}/shell-expected.txt
echo "ACTUAL RESULT:" echo "ACTUAL RESULT:"
@@ -164,7 +170,8 @@ version_test() {
if test "${REPORTED_VERSION}" == "${EXPECTED_VERSION}"; then if test "${REPORTED_VERSION}" == "${EXPECTED_VERSION}"; then
test_finish 0 test_finish 0
else else
printf "ERROR: Expected version ${EXPECTED_VERSION}, got ${REPORTED_VERSION}\n" echo "ERROR:" \
"Expected version ${EXPECTED_VERSION}, got ${REPORTED_VERSION}"
test_finish 1 test_finish 1
fi fi
} }
@@ -174,5 +181,3 @@ shell_command_test "shell.list-commands" "list-commands" \
"[ { \"arguments\": [ \"list-commands\" ], \"result\": 0 } ]" "" "[ { \"arguments\": [ \"list-commands\" ], \"result\": 0 } ]" ""
shell_command_test "shell.bogus" "give-me-a-beer" \ shell_command_test "shell.bogus" "give-me-a-beer" \
"[ { \"result\": 1, \"text\": \"'give-me-a-beer' command not supported.\" } ]" "" "[ { \"result\": 1, \"text\": \"'give-me-a-beer' command not supported.\" } ]" ""

View File

@@ -1,104 +0,0 @@
# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import unittest
from kea_conn import CARequest
class CARequestUnitTest(unittest.TestCase):
"""
This class is dedicated to testing CARequest class. That class
is responsible for generation of the body and headers.
"""
def setUp(self):
"""
This method is called before each test. Currently it does nothing.
"""
pass
def test_bodyWithoutParams(self):
"""
This test verifies if the CARequest object generates the request
content properly when there are no parameters.
"""
x = CARequest()
x.command = "foo"
x.generateBody()
self.assertEqual(x.content, '{ "command": "foo" }')
def test_bodyWithParams(self):
"""
This test verifies if the CARequest object generates the request
content properly when there are parameters.
"""
x = CARequest()
x.command = "foo"
x.params = '"bar": "baz"'
x.generateBody()
self.assertEqual(x.content, '{ "command": "foo", "parameters": { "bar": "baz" } }')
def checkHeader(self, headers, header_name, value):
"""
Checks if headers array contains an entry specified by header_name and that
its value matches specified value
"""
if header_name in headers:
if (headers[header_name] == value):
return True
else:
print ("Expected value: " + value + " does not match actual value: "
+ headers[header_name])
return ()
else:
print ("Expected header: " + header_name + " missing")
return (false)
def test_headers(self):
"""
This test checks if the headers are generated properly. Note that since
the content is not specified, it is 0. Therefore Content-Length is 0.
"""
x = CARequest()
x.generateHeaders()
self.assertTrue(self.checkHeader(x.headers, 'Content-Type', 'application/json'))
self.assertTrue(self.checkHeader(x.headers, 'Accept', '*/*'))
self.assertTrue(self.checkHeader(x.headers, 'Content-Length', "0"))
def test_headerLength(self):
"""
This test checks if the headers are generated properly. In this test there
is specific content of non-zero length, and its size should be reflected
in the header.
"""
x = CARequest()
x.content = '{ "command": "foo" }'
x.generateHeaders()
self.assertTrue(self.checkHeader(x.headers, 'Content-Length', str(len(x.content))))
def test_headerVersion(self):
"""
This test checks if the version reported in HTTP headers is generated properly.
"""
x = CARequest()
x.version = "1.2.3"
x.generateHeaders()
self.assertTrue(self.checkHeader(x.headers, 'User-Agent', 'Kea-shell/1.2.3'))
def tearDown(self):
"""
This method is called after each test. Currently it does nothing.
"""
pass
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,115 @@
#!@PYTHON@
# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
Kea shell unittest (python part)
"""
import unittest
from kea_conn import CARequest
class CARequestUnitTest(unittest.TestCase):
"""
This class is dedicated to testing CARequest class. That class
is responsible for generation of the body and headers.
"""
def setUp(self):
"""
This method is called before each test. Currently it does nothing.
"""
pass
def test_body_without_params(self):
"""
This test verifies if the CARequest object generates the request
content properly when there are no parameters.
"""
request = CARequest()
request.command = "foo"
request.generate_body()
self.assertEqual(request.content, '{ "command": "foo" }')
def test_body_with_params(self):
"""
This test verifies if the CARequest object generates the request
content properly when there are parameters.
"""
request = CARequest()
request.command = "foo"
request.params = '"bar": "baz"'
request.generate_body()
self.assertEqual(request.content,
'{ "command": "foo", "parameters": { "bar": "baz" } }')
@staticmethod
def check_header(headers, header_name, value):
"""
Checks if headers array contains an entry specified by
header_name and that its value matches specified value
"""
if header_name in headers:
if headers[header_name] == value:
return True
else:
print("Expected value: " + value +
" does not match actual value: " +
headers[header_name])
return False
else:
print("Expected header: " + header_name + " missing")
return False
def test_headers(self):
"""
This test checks if the headers are generated properly. Note that since
the content is not specified, it is 0. Therefore Content-Length is 0.
"""
request = CARequest()
request.generate_headers()
self.assertTrue(self.check_header(request.headers,
'Content-Type', 'application/json'))
self.assertTrue(self.check_header(request.headers,
'Accept', '*/*'))
self.assertTrue(self.check_header(request.headers,
'Content-Length', '0'))
def test_header_length(self):
"""
This test checks if the headers are generated properly. In
this test there is specific content of non-zero length, and
its size should be reflected in the header.
"""
request = CARequest()
request.content = '{ "command": "foo" }'
request.generate_headers()
self.assertTrue(self.check_header(request.headers, 'Content-Length',
str(len(request.content))))
def test_header_version(self):
"""
This test checks if the version reported in HTTP headers is
generated properly.
"""
request = CARequest()
request.version = "1.2.3"
request.generate_headers()
self.assertTrue(self.check_header(request.headers, 'User-Agent',
'Kea-shell/1.2.3'))
def tearDown(self):
"""
This method is called after each test. Currently it does nothing.
"""
pass
if __name__ == '__main__':
unittest.main()