diff --git a/watcher/conf/grafana_client.py b/watcher/conf/grafana_client.py index 47910c77b..b80a1fb1c 100644 --- a/watcher/conf/grafana_client.py +++ b/watcher/conf/grafana_client.py @@ -19,7 +19,10 @@ from oslo_config import cfg grafana_client = cfg.OptGroup(name='grafana_client', - title='Configuration Options for Grafana') + title='Configuration Options for Grafana', + help="See https://docs.openstack.org/watcher/lat" + "est/datasources/grafana.html for details " + "on how these options are used.") GRAFANA_CLIENT_OPTS = [ # TODO(Dantali0n) each individual metric could have its own token. @@ -31,7 +34,7 @@ GRAFANA_CLIENT_OPTS = [ # A similar structure to the database_map would solve this. cfg.StrOpt('base_url', default=None, - help="first part of the url (including https:// or http://) up " + help="First part of the url (including https:// or http://) up " "until project id part. " "Example: https://secure.org/api/datasource/proxy/"), cfg.DictOpt('project_id_map', @@ -48,7 +51,7 @@ GRAFANA_CLIENT_OPTS = [ 'instance_l3_cache_usage': None, 'instance_root_disk_size': None, }, - help="Mapping of grafana project ids to datasource metrics. " + help="Mapping of datasource metrics to grafana project ids. " "Dictionary values should be positive integers. " "Example: 7465"), cfg.DictOpt('database_map', @@ -65,7 +68,7 @@ GRAFANA_CLIENT_OPTS = [ 'instance_l3_cache_usage': None, 'instance_root_disk_size': None, }, - help="Mapping of grafana databases to datasource metrics. " + help="Mapping of datasource metrics to grafana databases. " "Values should be strings. Example: influx_production"), cfg.DictOpt('attribute_map', default={ @@ -81,10 +84,10 @@ GRAFANA_CLIENT_OPTS = [ 'instance_l3_cache_usage': None, 'instance_root_disk_size': None, }, - help="Mapping of resource attributes to datasource metrics. " + help="Mapping of datasource metrics to resource attributes. " "For a complete list of available attributes see " - "instance.py and node.py in " - "decision_engine/model/element. " + "https://docs.openstack.org/watcher/latest/datasources/gr" + "afana.html#attribute " "Values should be strings. Example: hostname"), cfg.DictOpt('translator_map', default={ @@ -100,7 +103,7 @@ GRAFANA_CLIENT_OPTS = [ 'instance_l3_cache_usage': None, 'instance_root_disk_size': None, }, - help="Mapping of grafana translators to datasource metrics. " + help="Mapping of datasource metrics to grafana translators. " "Values should be strings. Example: influxdb"), cfg.DictOpt('query_map', # {0} = aggregate @@ -121,12 +124,17 @@ GRAFANA_CLIENT_OPTS = [ 'instance_l3_cache_usage': None, 'instance_root_disk_size': None, }, - help="Mapping of grafana queries to datasource metrics. " + help="Mapping of datasource metrics to grafana queries. " "Values should be strings for which the .format method " - "will transform it. These queries will need to be " - "constructed using tools such as Postman. " - "Example: SELECT cpu FROM {4}.cpu_percent WHERE " - "host == '{1}' AND time > now()-{2}s")] + "will transform it. The transformation offers five " + "parameters to the query labeled {0} to {4}. {0} will be " + "replaced with the aggregate, {1} with the resource " + "attribute, {2} with the period, {3} with the " + "granularity and {4} with translator specifics for " + "InfluxDB this will be the retention period. " + "These queries will need to be constructed using tools " + "such as Postman. Example: SELECT cpu FROM {4}." + "cpu_percent WHERE host == '{1}' AND time > now()-{2}s")] def register_opts(conf): @@ -135,4 +143,4 @@ def register_opts(conf): def list_opts(): - return [('grafana_client', GRAFANA_CLIENT_OPTS)] + return [(grafana_client, GRAFANA_CLIENT_OPTS)] diff --git a/watcher/tests/conf/test_list_opts.py b/watcher/tests/conf/test_list_opts.py index f6a63d410..fb478c83e 100755 --- a/watcher/tests/conf/test_list_opts.py +++ b/watcher/tests/conf/test_list_opts.py @@ -16,6 +16,7 @@ # limitations under the License. import mock +from oslo_config import cfg from stevedore import extension from watcher.conf import opts @@ -74,7 +75,10 @@ class TestListOpts(base.TestCase): result = opts.list_opts() self.assertIsNotNone(result) - for section_name, options in result: + for name_or_group, options in result: + section_name = name_or_group + if isinstance(name_or_group, cfg.OptGroup): + section_name = name_or_group.name self.assertIn(section_name, expected_sections) self.assertTrue(len(options)) @@ -106,7 +110,10 @@ class TestListOpts(base.TestCase): result = opts.list_opts() self.assertIsNotNone(result) - for section_name, options in result: + for name_or_group, options in result: + section_name = name_or_group + if isinstance(name_or_group, cfg.OptGroup): + section_name = name_or_group.name self.assertIn(section_name, expected_sections) self.assertTrue(len(options))