Skip to content

Commit

Permalink
Api tests (#32)
Browse files Browse the repository at this point in the history
* feature: ability to invoke apis against gw pods

New optional block within the datapower net config to test invokes of APIs:

    api_tests:
      enabled: true
      apis:
        - name: testapi
          path: /testpath
          method: get
          headers: {}

Will produce metrics for size, time and response code
  • Loading branch information
rickymoorhouse authored Jun 11, 2022
1 parent f8ebb83 commit 14514ab
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 13 deletions.
58 changes: 56 additions & 2 deletions datapower_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class DataPowerNet():
password = None
use_kubeconfig = False
items = {}
api_tests = None

def __init__(self, config, trawler):
# Takes in config object and trawler instance it's behind
Expand All @@ -28,6 +29,9 @@ def __init__(self, config, trawler):
# Datapower username to use for REST calls
self.username = config.get('username', 'admin')
self.secret = config.get('secret', 'gateway-admin-secret')
api_test_config = config.get('api_tests', None)
if api_test_config and api_test_config['enabled'] == True:
self.api_tests = api_test_config['apis']
# Load password from secret `datapower_password`
try:
self.password = trawler.read_secret('datapower_password')
Expand Down Expand Up @@ -91,14 +95,17 @@ def fish(self):
namespace=i.metadata.namespace,
username=self.username,
password=password,
trawler=self.trawler)
trawler=self.trawler,
api_tests=self.api_tests
)
self.items[dp_key].gather_metrics()
logger.info("DataPowers in list: {}".format(len(pods)))
except client.rest.ApiException as exception:
logger.error("Error calling kubernetes API")
logger.debug(exception)



class DataPower():
""" Object representing each datapower pod """
domain = 'apiconnect'
Expand All @@ -109,10 +116,13 @@ class DataPower():
v5c = False
statistics_enabled = False
ip = '127.0.0.1'
port = 5554
apiPort = 9443
trawler = None
api_tests = None
labels = {}

def __init__(self, ip, port, name, namespace, username, password, trawler):
def __init__(self, ip, port, name, namespace, username, password, trawler, api_tests=None):
self.ip = ip
self.port = port
self.name = name
Expand All @@ -121,6 +131,7 @@ def __init__(self, ip, port, name, namespace, username, password, trawler):
self.password = password
self.get_info()
self.trawler = trawler
self.api_tests = api_tests
self.are_statistics_enabled()
self.labels = {"namespace": self.namespace}
logger.info('DataPower {} {} initialised at {}:{}'.format(self.name, self.v5c, self.ip, self.port))
Expand Down Expand Up @@ -194,6 +205,10 @@ def gather_metrics(self):
# Needs statistics enabled:
if self.statistics_enabled:
self.fetch_data('HTTPTransactions2', 'http')
if self.api_tests:
for api in self.api_tests:
self.invoke_api(api)


def fetch_data(self, provider, label, suffix=''):
""" fetch data from a status provider """
Expand Down Expand Up @@ -297,6 +312,45 @@ def gateway_peering_status(self):
self.trawler.set_gauge('datapower', "gateway_peering_primary_offset", entry["ReplicationOffset"],
pod_name=self.name, labels=labels)

def invoke_api(self, api):
""" invoke api_tests endpoints """
http_call = getattr(requests, api['method'])
try:
result = http_call(
"https://{}:{}{}".format(self.ip, self.apiPort, api['path']),
headers=api.get('headers', None),
timeout=5,
verify=False,
allow_redirects=False
)
elapsed_time = result.elapsed.microseconds
size = len(result.text)
status = result.status_code
self.trawler.set_gauge(
'datapower',
"invoke_api_{}_size".format(api['name']),
size,
pod_name=self.name, labels=self.labels)
self.trawler.set_gauge(
'datapower',
"invoke_api_{}_time".format(api['name']),
elapsed_time,
pod_name=self.name, labels=self.labels)
status_labels = self.labels
status_labels['code'] = status
self.trawler.set_gauge(
'datapower',
"invoke_api_{}_status_total".format(api['name']),
1,
pod_name=self.name, labels=self.labels)
except requests.RequestException:
status_labels = self.labels
status_labels['code'] = '000'
self.trawler.set_gauge(
'datapower',
"invoke_api_{}_status_total".format(api['name']),
0,
pod_name=self.name, labels=self.labels)

if __name__ == "__main__":
net = DataPowerNet()
Expand Down
47 changes: 36 additions & 11 deletions test_trawler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@
statistics_enabled = '{"Statistics":{"mAdminState":"enabled"}}'

fake_pod = kubernetes.client.V1Pod(
metadata=kubernetes.client.V1ObjectMeta(
name='testpod',
namespace='trawler-test',
annotations={"testAnnotation": "testValue"}
),
status=kubernetes.client.V1PodStatus(
conditions=[
kubernetes.client.V1PodCondition(type='Ready', status=True)
],
pod_ip="127.0.0.1"
)
metadata=kubernetes.client.V1ObjectMeta(
name='testpod',
namespace='trawler-test',
annotations={"testAnnotation": "testValue"}
),
status=kubernetes.client.V1PodStatus(
conditions=[
kubernetes.client.V1PodCondition(type='Ready', status=True)
],
pod_ip="127.0.0.1"
)
)



Expand Down Expand Up @@ -235,6 +235,31 @@ def test_datapower_instance_connecttimeout(caplog, mocker):
assert dp.ip == '127.0.0.1'
assert 'rest-mgmt' in caplog.text

def test_datapower_instance_api_test(caplog, mocker):
""" Test per gateway api testing """
caplog.set_level(logging.INFO)
api_tests = [
{"name":"test", "path": "/apitest", "method": "get"}
]
with requests_mock.mock() as m:
v6 = '{"APIConnectGatewayService":{"V5CompatibilityMode":"off"}}'
m.get('https://127.0.0.1:5554/mgmt/config/apiconnect/APIConnectGatewayService/default', text=v6)
m.get('https://127.0.0.1:5554/mgmt/config/apiconnect/Statistics', text=statistics_enabled)
m.get('https://127.0.0.1:9443/apitest', text='1')
dp = datapower_net.DataPower('127.0.0.1', '5554', 'myDp', 'namespace', 'admin', 'password', boaty, api_tests)
assert dp.name == 'myDp'
assert dp.ip == '127.0.0.1'
assert dp.api_tests == api_tests
dp.invoke_api(dp.api_tests[0])
assert prometheus_client.REGISTRY.get_sample_value(
'datapower_invoke_api_test_size',
labels={"pod": "myDp", "namespace": "namespace"}) == 1
assert prometheus_client.REGISTRY.get_sample_value(
'datapower_invoke_api_test_time',
labels={"pod": "myDp", "namespace": "namespace"})
assert prometheus_client.REGISTRY.get_sample_value(
'datapower_invoke_api_test_status_total',
labels={"pod": "myDp", "namespace": "namespace", "code": "200"})

def test_manager_fishing_error(mocker, caplog):
caplog.set_level(logging.INFO)
Expand Down

0 comments on commit 14514ab

Please sign in to comment.