Files
python-observabilityclient/observabilityclient/tests/unit/test_utils.py
Jaromir Wysoglad ccf4ace2b5 Enable providing keystone session for Prometheus
This enables us to create a PrometheusAPIClient, which uses a
keystone session when communicating with Prometheus, which
causes the requests to include an X-Auth-Token header
with the user's keystone token. This will enable observabilityclient
to authenticate when communicating with Aetos in the future.

Change-Id: I3693a6906efccdbb193ddd1e927ed83975592442
2025-04-17 10:57:57 -04:00

199 lines
7.3 KiB
Python

# Copyright 2023 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from unittest import mock
import testtools
from observabilityclient import prometheus_client
from observabilityclient.utils import metric_utils
class GetConfigFileTest(testtools.TestCase):
def setUp(self):
super(GetConfigFileTest, self).setUp()
def test_current_dir(self):
with mock.patch.object(os.path, 'exists', return_value=True), \
mock.patch.object(metric_utils, 'open') as m:
metric_utils.get_config_file()
m.assert_called_with(metric_utils.CONFIG_FILE_NAME, 'r')
def test_path_order(self):
expected = [mock.call(metric_utils.CONFIG_FILE_NAME, 'r'),
mock.call((f"{os.environ['HOME']}/.config/openstack/"
f"{metric_utils.CONFIG_FILE_NAME}")),
mock.call((f"/etc/openstack/"
f"{metric_utils.CONFIG_FILE_NAME}"))]
with mock.patch.object(os.path, 'exists', return_value=False) as m:
ret = metric_utils.get_config_file()
m.call_args_list == expected
self.assertIsNone(ret)
class GetPrometheusClientTest(testtools.TestCase):
def setUp(self):
super(GetPrometheusClientTest, self).setUp()
config_data = 'host: "somehost"\nport: "1234"'
self.config_file = mock.mock_open(read_data=config_data)("name", 'r')
def test_get_prometheus_client_from_file(self):
with mock.patch.object(metric_utils, 'get_config_file',
return_value=self.config_file), \
mock.patch.object(prometheus_client.PrometheusAPIClient,
"__init__", return_value=None) as m:
metric_utils.get_prometheus_client()
m.assert_called_with("somehost:1234", None)
def test_get_prometheus_client_env_override(self):
with mock.patch.dict(os.environ,
{'PROMETHEUS_HOST': 'env_override'}), \
mock.patch.object(metric_utils, 'get_config_file',
return_value=self.config_file), \
mock.patch.object(prometheus_client.PrometheusAPIClient,
"__init__", return_value=None) as m:
metric_utils.get_prometheus_client()
m.assert_called_with("env_override:1234", None)
def test_get_prometheus_client_no_config_file(self):
patched_env = {'PROMETHEUS_HOST': 'env_override',
'PROMETHEUS_PORT': 'env_port'}
with mock.patch.dict(os.environ, patched_env), \
mock.patch.object(metric_utils, 'get_config_file',
return_value=None), \
mock.patch.object(prometheus_client.PrometheusAPIClient,
"__init__", return_value=None) as m:
metric_utils.get_prometheus_client()
m.assert_called_with("env_override:env_port", None)
def test_get_prometheus_client_missing_configuration(self):
with mock.patch.dict(os.environ, {}), \
mock.patch.object(metric_utils, 'get_config_file',
return_value=None), \
mock.patch.object(prometheus_client.PrometheusAPIClient,
"__init__", return_value=None):
self.assertRaises(metric_utils.ConfigurationError,
metric_utils.get_prometheus_client)
class FormatLabelsTest(testtools.TestCase):
def setUp(self):
super(FormatLabelsTest, self).setUp()
def test_format_labels_with_normal_labels(self):
input_dict = {"label_key1": "label_value1",
"label_key2": "label_value2"}
expected = "label_key1='label_value1', label_key2='label_value2'"
ret = metric_utils.format_labels(input_dict)
self.assertEqual(expected, ret)
def test_format_labels_with_quoted_labels(self):
input_dict = {"label_key1": "'label_value1'",
"label_key2": "'label_value2'"}
expected = "label_key1='label_value1', label_key2='label_value2'"
ret = metric_utils.format_labels(input_dict)
self.assertEqual(expected, ret)
class Metrics2ColsTest(testtools.TestCase):
def setUp(self):
super(Metrics2ColsTest, self).setUp()
def test_metrics2cols(self):
metric = {
'value': [
1234567,
5
],
'metric': {
'label1': 'value1',
'label2': 'value2',
}
}
input_metrics = [prometheus_client.PrometheusMetric(metric)]
expected = (['label1', 'label2', 'value'], [['value1', 'value2', 5]])
ret = metric_utils.metrics2cols(input_metrics)
self.assertEqual(expected, ret)
def test_metrics2cols_column_ordering(self):
metric = {
'value': [
1234567,
5
],
'metric': {
'a_label1': 'value1',
'b_label2': 'value2',
}
}
input_metrics = [prometheus_client.PrometheusMetric(metric)]
expected = (['a_label1', 'b_label2', 'value'],
[['value1', 'value2', 5]])
ret = metric_utils.metrics2cols(input_metrics)
self.assertEqual(expected, ret)
metric = {
'value': [
1234567,
5
],
'metric': {
'b_label1': 'value1',
'a_label2': 'value2',
}
}
input_metrics = [prometheus_client.PrometheusMetric(metric)]
expected = (['a_label2', 'b_label1', 'value'],
[['value2', 'value1', 5]])
ret = metric_utils.metrics2cols(input_metrics)
self.assertEqual(expected, ret)
metric1 = {
'value': [
1234567,
5
],
'metric': {
'b_label1': 'value1',
'a_label2': 'value2',
}
}
metric2 = {
'value': [
1234567,
5
],
'metric': {
'b_label1': 'value1',
'a_label2': 'value2',
'd_label3': 'value3',
'c_label4': 'value4',
}
}
input_metrics = [prometheus_client.PrometheusMetric(metric1),
prometheus_client.PrometheusMetric(metric2)]
expected = (['a_label2', 'b_label1', 'c_label4', 'd_label3', 'value'],
[['value2', 'value1', '', '', 5],
['value2', 'value1', 'value4', 'value3', 5]]
)
ret = metric_utils.metrics2cols(input_metrics)
self.assertEqual(expected, ret)