promtext-cli 0.1.2.dev89__tar.gz → 0.1.2.dev93__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.copier-answers.yml +6 -6
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.forgejo/workflows/lint.yaml +3 -3
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.forgejo/workflows/test.yaml +1 -1
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/PKG-INFO +1 -1
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/promtext_cli/main.py +48 -24
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/pyproject.toml +4 -2
- promtext_cli-0.1.2.dev93/tests/test_blackbox.py +48 -0
- promtext_cli-0.1.2.dev93/tests/test_functional.py +342 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/uv.lock +11 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.commitlintrc.yaml +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.forgejo/workflows/commitlint.yaml +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.forgejo/workflows/publish.yaml +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.gitignore +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/.pre-commit-config.yaml +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/README.md +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/cliff.toml +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/promtext_cli/__init__.py +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/renovate.json +0 -0
- {promtext_cli-0.1.2.dev89 → promtext_cli-0.1.2.dev93}/tests/.gitkeep +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Changes here will be overwritten by Copier.
|
|
2
|
-
_commit: 0.7.
|
|
2
|
+
_commit: 0.7.7
|
|
3
3
|
_src_path: https://codeberg.org/margau/copier-python-uv.git
|
|
4
|
-
code_dir:
|
|
4
|
+
code_dir: promtext_cli
|
|
5
5
|
container: false
|
|
6
6
|
forgejo_publish: true
|
|
7
7
|
forgejo_url: https://codeberg.org/margau/promtext-cli
|
|
8
|
-
ignore_pylint:
|
|
9
|
-
ignore_pytest:
|
|
10
|
-
ignore_ruff:
|
|
11
|
-
ignore_ruff_format:
|
|
8
|
+
ignore_pylint: false
|
|
9
|
+
ignore_pytest: false
|
|
10
|
+
ignore_ruff: false
|
|
11
|
+
ignore_ruff_format: false
|
|
12
12
|
project_description: Prometheus Textfile Tooling
|
|
13
13
|
project_name: promtext-cli
|
|
14
14
|
pypi_publish: true
|
|
@@ -20,8 +20,8 @@ jobs:
|
|
|
20
20
|
- name: Install the project
|
|
21
21
|
run: uv sync --locked --all-extras --dev
|
|
22
22
|
- name: check with ruff
|
|
23
|
-
run: uv run ruff check
|
|
23
|
+
run: uv run ruff check promtext_cli tests
|
|
24
24
|
- name: format with ruff
|
|
25
|
-
run: uv run ruff format --check
|
|
25
|
+
run: uv run ruff format --check promtext_cli tests
|
|
26
26
|
- name: check with pylint
|
|
27
|
-
run: uv run pylint
|
|
27
|
+
run: uv run pylint promtext_cli tests # TODO: Check if there is a need for special pytest-related pylint rules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: promtext-cli
|
|
3
|
-
Version: 0.1.2.
|
|
3
|
+
Version: 0.1.2.dev93
|
|
4
4
|
Summary: Prometheus Textfile Tooling
|
|
5
5
|
Project-URL: Documentation, https://codeberg.org/margau/promtext-cli/src/branch/main#readme
|
|
6
6
|
Project-URL: Issues, https://codeberg.org/margau/promtext-cli/issues
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""promtext_cli is providing a CLI to cleanly update prometheus textfiles from scripts"""
|
|
2
2
|
|
|
3
|
+
# pylint: disable=C0116,R0914,R0912,R0915
|
|
4
|
+
# this rules will be fixed by a object-oriented refactoring
|
|
5
|
+
|
|
3
6
|
import argparse
|
|
4
7
|
from pathlib import Path
|
|
5
8
|
import logging
|
|
@@ -8,37 +11,43 @@ import sys
|
|
|
8
11
|
from prometheus_client.parser import text_string_to_metric_families
|
|
9
12
|
from prometheus_client import CollectorRegistry, Gauge, write_to_textfile
|
|
10
13
|
|
|
14
|
+
|
|
11
15
|
def promtext():
|
|
12
16
|
# setup argpars
|
|
13
17
|
# required file first
|
|
14
|
-
parser = argparse.ArgumentParser(description=
|
|
18
|
+
parser = argparse.ArgumentParser(description="Prometheus textfile helper")
|
|
15
19
|
parser.add_argument(
|
|
16
|
-
|
|
20
|
+
"filename",
|
|
17
21
|
type=str,
|
|
18
|
-
help=
|
|
19
|
-
|
|
22
|
+
help="Path to existing or new prometheus textfile, will be updated",
|
|
23
|
+
)
|
|
20
24
|
|
|
21
25
|
# metric name, required
|
|
22
|
-
parser.add_argument(
|
|
23
|
-
'metric',
|
|
24
|
-
type=str,
|
|
25
|
-
help='metric name (new or updated)')
|
|
26
|
+
parser.add_argument("metric", type=str, help="metric name (new or updated)")
|
|
26
27
|
|
|
27
28
|
# metric value as int/float, required
|
|
28
|
-
parser.add_argument(
|
|
29
|
+
parser.add_argument("value", type=float, help="metric value")
|
|
29
30
|
|
|
30
31
|
# metric documentation as optional argument
|
|
31
32
|
parser.add_argument(
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
"--docs",
|
|
34
|
+
type=str,
|
|
35
|
+
help="metric documentation",
|
|
36
|
+
default="metric appended by promtext-cli",
|
|
37
|
+
)
|
|
34
38
|
|
|
35
39
|
# labels, key-value, minimum 0, repeatable
|
|
36
|
-
parser.add_argument(
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--label", metavar="KEY=VALUE", help="label key=value pairs", action="append"
|
|
42
|
+
)
|
|
37
43
|
|
|
38
44
|
# log level from argparse
|
|
39
45
|
parser.add_argument(
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
"-v",
|
|
47
|
+
"--verbose",
|
|
48
|
+
action="store_const",
|
|
49
|
+
dest="loglevel",
|
|
50
|
+
const=logging.INFO,
|
|
42
51
|
)
|
|
43
52
|
args = parser.parse_args()
|
|
44
53
|
logging.basicConfig(level=args.loglevel)
|
|
@@ -52,7 +61,7 @@ def promtext():
|
|
|
52
61
|
|
|
53
62
|
# check if args.filename exists with pathlib
|
|
54
63
|
if textfile.is_file():
|
|
55
|
-
for f in text_string_to_metric_families(textfile.read_text()):
|
|
64
|
+
for f in text_string_to_metric_families(textfile.read_text(encoding="utf-8")):
|
|
56
65
|
# per metric: iterate over samples, create metric in registry
|
|
57
66
|
m = False
|
|
58
67
|
samples = []
|
|
@@ -63,8 +72,13 @@ def promtext():
|
|
|
63
72
|
labelnames = list(samples[0].labels.keys())
|
|
64
73
|
# metric-type specific init
|
|
65
74
|
if f.type == "gauge":
|
|
66
|
-
m = Gauge(
|
|
67
|
-
|
|
75
|
+
m = Gauge(
|
|
76
|
+
f.name,
|
|
77
|
+
f.documentation,
|
|
78
|
+
unit=f.unit,
|
|
79
|
+
labelnames=labelnames,
|
|
80
|
+
registry=registry,
|
|
81
|
+
)
|
|
68
82
|
else:
|
|
69
83
|
# we don't support other types yet, continue in these cases
|
|
70
84
|
logger.warning("unsupported metric type %s, dropping", f.type)
|
|
@@ -76,8 +90,11 @@ def promtext():
|
|
|
76
90
|
else:
|
|
77
91
|
m.set(s.value)
|
|
78
92
|
metrics[f.name] = m
|
|
79
|
-
logger.info(
|
|
80
|
-
|
|
93
|
+
logger.info(
|
|
94
|
+
"copy gauge metric %s with labels %s from old file",
|
|
95
|
+
f.name,
|
|
96
|
+
", ".join(labelnames),
|
|
97
|
+
)
|
|
81
98
|
else:
|
|
82
99
|
logger.warning("got empty metric %s from old file, dropping", f.name)
|
|
83
100
|
|
|
@@ -99,18 +116,24 @@ def promtext():
|
|
|
99
116
|
labelvalues = labels.values()
|
|
100
117
|
else:
|
|
101
118
|
m = metrics[args.metric]
|
|
102
|
-
|
|
119
|
+
|
|
120
|
+
# There is no way to access existing labelnames directly
|
|
121
|
+
# pylint: disable=W0212
|
|
103
122
|
old_labelnames = list(m._labelnames)
|
|
104
123
|
for la in old_labelnames:
|
|
105
124
|
logger.info("processing label %s", la)
|
|
106
|
-
if la in labels:
|
|
125
|
+
if la in labels: # labelvalues are needed in order!
|
|
107
126
|
labelvalues.append(labels[la])
|
|
108
127
|
else:
|
|
109
128
|
logger.error("previously known label '%s' missing, cannot update!", la)
|
|
110
129
|
sys.exit(1)
|
|
111
130
|
if len(old_labelnames) != len(labels.keys()):
|
|
112
|
-
logger.error(
|
|
113
|
-
|
|
131
|
+
logger.error(
|
|
132
|
+
"labelnames for metric %s not the same, cannot update! Old: %s, New: %s",
|
|
133
|
+
args.metric,
|
|
134
|
+
old_labelnames,
|
|
135
|
+
list(labels.keys()),
|
|
136
|
+
)
|
|
114
137
|
sys.exit(1)
|
|
115
138
|
logger.info("updating metric %s", args.metric)
|
|
116
139
|
|
|
@@ -124,5 +147,6 @@ def promtext():
|
|
|
124
147
|
write_to_textfile(args.filename, registry)
|
|
125
148
|
logger.info("wrote to %s", args.filename)
|
|
126
149
|
|
|
127
|
-
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
128
152
|
promtext()
|
|
@@ -36,11 +36,13 @@ dev = [
|
|
|
36
36
|
"pylint>=4.0.5",
|
|
37
37
|
"pytest>=9.0.3",
|
|
38
38
|
"coverage>=7.14.0",
|
|
39
|
+
"cli-test-helpers>=4.2.0",
|
|
39
40
|
]
|
|
40
41
|
|
|
42
|
+
[tool.uv]
|
|
43
|
+
cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true } }]
|
|
44
|
+
|
|
41
45
|
[tool.coverage.run]
|
|
42
46
|
source = ["src", "tests"]
|
|
43
47
|
|
|
44
|
-
cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true } }]
|
|
45
|
-
|
|
46
48
|
# TODO: Dev/CI scripts for lint & co.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# pylint: disable=R0801
|
|
2
|
+
"""This script does blackbox-like testing of the promtext cli tool"""
|
|
3
|
+
|
|
4
|
+
import shutil
|
|
5
|
+
from cli_test_helpers import shell
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_entrypoint():
|
|
9
|
+
"""
|
|
10
|
+
Is entrypoint script installed? (pyproject.toml)
|
|
11
|
+
"""
|
|
12
|
+
assert shutil.which("promtext")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_help():
|
|
16
|
+
"""
|
|
17
|
+
Does the help command work?
|
|
18
|
+
"""
|
|
19
|
+
result = shell("promtext --help")
|
|
20
|
+
assert result.exit_code == 0
|
|
21
|
+
assert "usage:" in result.stdout
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_empty():
|
|
25
|
+
"""
|
|
26
|
+
Does the command fails with no arguments?
|
|
27
|
+
"""
|
|
28
|
+
result = shell("promtext")
|
|
29
|
+
assert result.exit_code == 2
|
|
30
|
+
assert "usage:" in result.stderr
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_new_file(tmp_path):
|
|
34
|
+
"""
|
|
35
|
+
Does the command create a new file with metrics content?
|
|
36
|
+
"""
|
|
37
|
+
promfile = tmp_path / "new_file.prom"
|
|
38
|
+
result = shell(f"promtext {promfile} test_metric 0")
|
|
39
|
+
assert result.exit_code == 0
|
|
40
|
+
assert promfile.exists()
|
|
41
|
+
assert promfile.read_text() == (
|
|
42
|
+
"# HELP test_metric metric appended by promtext-cli"
|
|
43
|
+
"\n"
|
|
44
|
+
"# TYPE test_metric gauge"
|
|
45
|
+
"\n"
|
|
46
|
+
"test_metric 0.0"
|
|
47
|
+
"\n"
|
|
48
|
+
)
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# pylint: disable=R0801,W0511
|
|
2
|
+
"""This script does functional testing by calling the methods directly"""
|
|
3
|
+
|
|
4
|
+
from cli_test_helpers import ArgvContext
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
import promtext_cli.main
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_new_file(tmp_path):
|
|
11
|
+
"""
|
|
12
|
+
Does the command create a new file with metrics content?
|
|
13
|
+
"""
|
|
14
|
+
promfile = tmp_path / "new_file.prom"
|
|
15
|
+
with ArgvContext("promtext", str(promfile), "test_metric", "0"):
|
|
16
|
+
promtext_cli.main.promtext()
|
|
17
|
+
assert promfile.exists()
|
|
18
|
+
assert promfile.read_text() == (
|
|
19
|
+
"# HELP test_metric metric appended by promtext-cli"
|
|
20
|
+
"\n"
|
|
21
|
+
"# TYPE test_metric gauge"
|
|
22
|
+
"\n"
|
|
23
|
+
"test_metric 0.0"
|
|
24
|
+
"\n"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_labels(tmp_path):
|
|
29
|
+
"""
|
|
30
|
+
Does the command create a new file with metrics content?
|
|
31
|
+
"""
|
|
32
|
+
promfile = tmp_path / "label_file.prom"
|
|
33
|
+
with ArgvContext(
|
|
34
|
+
"promtext", "--label", "testlabel=testvalue", str(promfile), "test_metric", 0
|
|
35
|
+
):
|
|
36
|
+
promtext_cli.main.promtext()
|
|
37
|
+
assert promfile.exists()
|
|
38
|
+
assert promfile.read_text() == (
|
|
39
|
+
"# HELP test_metric metric appended by promtext-cli"
|
|
40
|
+
"\n"
|
|
41
|
+
"# TYPE test_metric gauge"
|
|
42
|
+
"\n"
|
|
43
|
+
'test_metric{testlabel="testvalue"} 0.0'
|
|
44
|
+
"\n"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_existing_metric_append_metric(tmp_path):
|
|
49
|
+
"""
|
|
50
|
+
Does the command append a new metric to an existing file
|
|
51
|
+
with metrics content and preserve existing metrics?
|
|
52
|
+
"""
|
|
53
|
+
promfile = tmp_path / "existing_file.prom"
|
|
54
|
+
promfile.write_text(
|
|
55
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
56
|
+
"\n"
|
|
57
|
+
"# TYPE existing_metric gauge"
|
|
58
|
+
"\n"
|
|
59
|
+
'existing_metric{testlabel="testvalue"} 0.0'
|
|
60
|
+
"\n"
|
|
61
|
+
)
|
|
62
|
+
with ArgvContext(
|
|
63
|
+
"promtext", "--label", "testlabel=testvalue", str(promfile), "new_metric", 0
|
|
64
|
+
):
|
|
65
|
+
promtext_cli.main.promtext()
|
|
66
|
+
assert promfile.exists()
|
|
67
|
+
assert promfile.read_text() == (
|
|
68
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
69
|
+
"\n"
|
|
70
|
+
"# TYPE existing_metric gauge"
|
|
71
|
+
"\n"
|
|
72
|
+
'existing_metric{testlabel="testvalue"} 0.0'
|
|
73
|
+
"\n"
|
|
74
|
+
"# HELP new_metric metric appended by promtext-cli"
|
|
75
|
+
"\n"
|
|
76
|
+
"# TYPE new_metric gauge"
|
|
77
|
+
"\n"
|
|
78
|
+
'new_metric{testlabel="testvalue"} 0.0'
|
|
79
|
+
"\n"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_existing_metric_append_labelvalue(tmp_path):
|
|
84
|
+
"""
|
|
85
|
+
Does the command append a new metric to an existing file
|
|
86
|
+
with metrics content and preserve existing metrics?
|
|
87
|
+
"""
|
|
88
|
+
promfile = tmp_path / "existing_file.prom"
|
|
89
|
+
promfile.write_text(
|
|
90
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
91
|
+
"\n"
|
|
92
|
+
"# TYPE existing_metric gauge"
|
|
93
|
+
"\n"
|
|
94
|
+
'existing_metric{testlabel="existing"} 0.0'
|
|
95
|
+
"\n"
|
|
96
|
+
)
|
|
97
|
+
with ArgvContext(
|
|
98
|
+
"promtext", "--label", "testlabel=new", str(promfile), "existing_metric", 0
|
|
99
|
+
):
|
|
100
|
+
promtext_cli.main.promtext()
|
|
101
|
+
assert promfile.exists()
|
|
102
|
+
assert promfile.read_text() == (
|
|
103
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
104
|
+
"\n"
|
|
105
|
+
"# TYPE existing_metric gauge"
|
|
106
|
+
"\n"
|
|
107
|
+
'existing_metric{testlabel="existing"} 0.0'
|
|
108
|
+
"\n"
|
|
109
|
+
'existing_metric{testlabel="new"} 0.0'
|
|
110
|
+
"\n"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_existing_metric_multilabel(tmp_path):
|
|
115
|
+
"""
|
|
116
|
+
Does the command append a new metric to an existing file
|
|
117
|
+
with metrics content and preserve existing metrics?
|
|
118
|
+
"""
|
|
119
|
+
promfile = tmp_path / "existing_file.prom"
|
|
120
|
+
promfile.write_text(
|
|
121
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
122
|
+
"\n"
|
|
123
|
+
"# TYPE existing_metric gauge"
|
|
124
|
+
"\n"
|
|
125
|
+
'existing_metric{first="existing", second="existing"} 0.0'
|
|
126
|
+
"\n"
|
|
127
|
+
)
|
|
128
|
+
with ArgvContext(
|
|
129
|
+
"promtext",
|
|
130
|
+
"--label",
|
|
131
|
+
"first=new",
|
|
132
|
+
"--label",
|
|
133
|
+
"second=new",
|
|
134
|
+
str(promfile),
|
|
135
|
+
"existing_metric",
|
|
136
|
+
"42",
|
|
137
|
+
):
|
|
138
|
+
promtext_cli.main.promtext()
|
|
139
|
+
assert promfile.exists()
|
|
140
|
+
assert promfile.read_text() == (
|
|
141
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
142
|
+
"\n"
|
|
143
|
+
"# TYPE existing_metric gauge"
|
|
144
|
+
"\n"
|
|
145
|
+
'existing_metric{first="existing",second="existing"} 0.0'
|
|
146
|
+
"\n"
|
|
147
|
+
'existing_metric{first="new",second="new"} 42.0'
|
|
148
|
+
"\n"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_existing_metric_overwrite(tmp_path):
|
|
153
|
+
"""
|
|
154
|
+
Does the command overwrite a metric/labelset
|
|
155
|
+
"""
|
|
156
|
+
promfile = tmp_path / "existing_file.prom"
|
|
157
|
+
promfile.write_text(
|
|
158
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
159
|
+
"\n"
|
|
160
|
+
"# TYPE existing_metric gauge"
|
|
161
|
+
"\n"
|
|
162
|
+
'existing_metric{testlabel="existing"} 0.0'
|
|
163
|
+
"\n"
|
|
164
|
+
)
|
|
165
|
+
with ArgvContext(
|
|
166
|
+
"promtext",
|
|
167
|
+
"--label",
|
|
168
|
+
"testlabel=existing",
|
|
169
|
+
str(promfile),
|
|
170
|
+
"existing_metric",
|
|
171
|
+
"42",
|
|
172
|
+
):
|
|
173
|
+
promtext_cli.main.promtext()
|
|
174
|
+
assert promfile.exists()
|
|
175
|
+
assert promfile.read_text() == (
|
|
176
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
177
|
+
"\n"
|
|
178
|
+
"# TYPE existing_metric gauge"
|
|
179
|
+
"\n"
|
|
180
|
+
'existing_metric{testlabel="existing"} 42.0'
|
|
181
|
+
"\n"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_existing_metric_plain(tmp_path):
|
|
186
|
+
"""
|
|
187
|
+
Does the command overwrite a metric without a label?
|
|
188
|
+
"""
|
|
189
|
+
promfile = tmp_path / "existing_file.prom"
|
|
190
|
+
promfile.write_text(
|
|
191
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
192
|
+
"\n"
|
|
193
|
+
"# TYPE existing_metric gauge"
|
|
194
|
+
"\n"
|
|
195
|
+
"existing_metric 0.0"
|
|
196
|
+
"\n"
|
|
197
|
+
)
|
|
198
|
+
with ArgvContext("promtext", str(promfile), "existing_metric", "42"):
|
|
199
|
+
promtext_cli.main.promtext()
|
|
200
|
+
assert promfile.exists()
|
|
201
|
+
assert promfile.read_text() == (
|
|
202
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
203
|
+
"\n"
|
|
204
|
+
"# TYPE existing_metric gauge"
|
|
205
|
+
"\n"
|
|
206
|
+
"existing_metric 42.0"
|
|
207
|
+
"\n"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def test_existing_metric_labeldrop(tmp_path, capsys):
|
|
212
|
+
"""
|
|
213
|
+
missing labels are not possible, promtext should fail
|
|
214
|
+
"""
|
|
215
|
+
promfile = tmp_path / "existing_file.prom"
|
|
216
|
+
promfile.write_text(
|
|
217
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
218
|
+
"\n"
|
|
219
|
+
"# TYPE existing_metric gauge"
|
|
220
|
+
"\n"
|
|
221
|
+
'existing_metric{testlabel="existing"} 0.0'
|
|
222
|
+
"\n"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
with (
|
|
226
|
+
ArgvContext("promtext", str(promfile), "existing_metric", "42"),
|
|
227
|
+
pytest.raises(SystemExit) as pytest_wrapped_e,
|
|
228
|
+
):
|
|
229
|
+
promtext_cli.main.promtext()
|
|
230
|
+
assert promfile.exists()
|
|
231
|
+
assert promfile.read_text() == (
|
|
232
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
233
|
+
"\n"
|
|
234
|
+
"# TYPE existing_metric gauge"
|
|
235
|
+
"\n"
|
|
236
|
+
'existing_metric{testlabel="existing"} 0.0'
|
|
237
|
+
"\n"
|
|
238
|
+
) # the content is not changed
|
|
239
|
+
# check that promtext exits correctly
|
|
240
|
+
assert pytest_wrapped_e.type is SystemExit
|
|
241
|
+
assert pytest_wrapped_e.value.code == 1
|
|
242
|
+
captured = capsys.readouterr()
|
|
243
|
+
assert (
|
|
244
|
+
"ERROR:promtext_cli.main:previously known label 'testlabel' missing, cannot update!"
|
|
245
|
+
in captured.err
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_existing_metric_labelchange(tmp_path, capsys):
|
|
250
|
+
"""
|
|
251
|
+
changing labels are not possible, promtext should fail
|
|
252
|
+
"""
|
|
253
|
+
promfile = tmp_path / "existing_file.prom"
|
|
254
|
+
promfile.write_text(
|
|
255
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
256
|
+
"\n"
|
|
257
|
+
"# TYPE existing_metric gauge"
|
|
258
|
+
"\n"
|
|
259
|
+
'existing_metric{existinglabel="existing"} 0.0'
|
|
260
|
+
"\n"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
with (
|
|
264
|
+
ArgvContext(
|
|
265
|
+
"promtext",
|
|
266
|
+
"--label",
|
|
267
|
+
"newlabel=new",
|
|
268
|
+
str(promfile),
|
|
269
|
+
"existing_metric",
|
|
270
|
+
"42",
|
|
271
|
+
),
|
|
272
|
+
pytest.raises(SystemExit) as pytest_wrapped_e,
|
|
273
|
+
):
|
|
274
|
+
promtext_cli.main.promtext()
|
|
275
|
+
assert promfile.exists()
|
|
276
|
+
assert promfile.read_text() == (
|
|
277
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
278
|
+
"\n"
|
|
279
|
+
"# TYPE existing_metric gauge"
|
|
280
|
+
"\n"
|
|
281
|
+
'existing_metric{existinglabel="existing"} 0.0'
|
|
282
|
+
"\n"
|
|
283
|
+
) # the content is not changed
|
|
284
|
+
# check that promtext exits correctly
|
|
285
|
+
assert pytest_wrapped_e.type is SystemExit
|
|
286
|
+
assert pytest_wrapped_e.value.code == 1
|
|
287
|
+
captured = capsys.readouterr()
|
|
288
|
+
assert (
|
|
289
|
+
"ERROR:promtext_cli.main:previously known label 'existinglabel' missing, cannot update!"
|
|
290
|
+
in captured.err
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def test_existing_metric_labeladd(tmp_path, capsys):
|
|
295
|
+
"""
|
|
296
|
+
adding new labels are not possible, promtext should fail
|
|
297
|
+
"""
|
|
298
|
+
promfile = tmp_path / "existing_file.prom"
|
|
299
|
+
promfile.write_text(
|
|
300
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
301
|
+
"\n"
|
|
302
|
+
"# TYPE existing_metric gauge"
|
|
303
|
+
"\n"
|
|
304
|
+
'existing_metric{existinglabel="existing"} 0.0'
|
|
305
|
+
"\n"
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
with (
|
|
309
|
+
ArgvContext(
|
|
310
|
+
"promtext",
|
|
311
|
+
"--label",
|
|
312
|
+
"existinglabel=existing",
|
|
313
|
+
"--label",
|
|
314
|
+
"newlabel=new",
|
|
315
|
+
str(promfile),
|
|
316
|
+
"existing_metric",
|
|
317
|
+
"42",
|
|
318
|
+
),
|
|
319
|
+
pytest.raises(SystemExit) as pytest_wrapped_e,
|
|
320
|
+
):
|
|
321
|
+
promtext_cli.main.promtext()
|
|
322
|
+
assert promfile.exists()
|
|
323
|
+
assert promfile.read_text() == (
|
|
324
|
+
"# HELP existing_metric metric appended by promtext-cli"
|
|
325
|
+
"\n"
|
|
326
|
+
"# TYPE existing_metric gauge"
|
|
327
|
+
"\n"
|
|
328
|
+
'existing_metric{existinglabel="existing"} 0.0'
|
|
329
|
+
"\n"
|
|
330
|
+
) # the content is not changed
|
|
331
|
+
# check that promtext exits correctly
|
|
332
|
+
assert pytest_wrapped_e.type is SystemExit
|
|
333
|
+
assert pytest_wrapped_e.value.code == 1
|
|
334
|
+
captured = capsys.readouterr()
|
|
335
|
+
assert (
|
|
336
|
+
"ERROR:promtext_cli.main:labelnames for metric existing_metric not the same, cannot update"
|
|
337
|
+
in captured.err
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
# TODO: Test docs in promtext
|
|
342
|
+
# TODO: Test non-gauge-values
|
|
@@ -19,6 +19,15 @@ wheels = [
|
|
|
19
19
|
{ url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753", size = 276445, upload-time = "2026-02-07T23:35:05.344Z" },
|
|
20
20
|
]
|
|
21
21
|
|
|
22
|
+
[[package]]
|
|
23
|
+
name = "cli-test-helpers"
|
|
24
|
+
version = "4.2.0"
|
|
25
|
+
source = { registry = "https://pypi.org/simple" }
|
|
26
|
+
sdist = { url = "https://files.pythonhosted.org/packages/21/7f/e75d5401607fe7ecbdb61f2834c938188d5701625006851214063ae9d59b/cli_test_helpers-4.2.0.tar.gz", hash = "sha256:c7dc8f26a1ca30ff63d75ef2f259ec7044e1c4a78dede204627e069861257b06", size = 50969, upload-time = "2025-12-15T09:54:21.464Z" }
|
|
27
|
+
wheels = [
|
|
28
|
+
{ url = "https://files.pythonhosted.org/packages/02/4b/3d6ef5cfb906b2e53b8af97023ac17d103b9ba1a795587d3a2b6ad9a8e1e/cli_test_helpers-4.2.0-py3-none-any.whl", hash = "sha256:6b644e0abc3e9a22fae9765cde96a525ca317f7e296a5f25ff1dcfebfec1119a", size = 35706, upload-time = "2025-12-15T09:54:20.561Z" },
|
|
29
|
+
]
|
|
30
|
+
|
|
22
31
|
[[package]]
|
|
23
32
|
name = "colorama"
|
|
24
33
|
version = "0.4.6"
|
|
@@ -234,6 +243,7 @@ dependencies = [
|
|
|
234
243
|
|
|
235
244
|
[package.dev-dependencies]
|
|
236
245
|
dev = [
|
|
246
|
+
{ name = "cli-test-helpers" },
|
|
237
247
|
{ name = "coverage" },
|
|
238
248
|
{ name = "pylint" },
|
|
239
249
|
{ name = "pytest" },
|
|
@@ -245,6 +255,7 @@ requires-dist = [{ name = "prometheus-client" }]
|
|
|
245
255
|
|
|
246
256
|
[package.metadata.requires-dev]
|
|
247
257
|
dev = [
|
|
258
|
+
{ name = "cli-test-helpers", specifier = ">=4.2.0" },
|
|
248
259
|
{ name = "coverage", specifier = ">=7.14.0" },
|
|
249
260
|
{ name = "pylint", specifier = ">=4.0.5" },
|
|
250
261
|
{ name = "pytest", specifier = ">=9.0.3" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|