qontract-reconcile 0.10.2.dev167__py3-none-any.whl → 0.10.2.dev168__py3-none-any.whl
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.
- {qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/RECORD +10 -8
- reconcile/dashdotdb_slo.py +45 -156
- reconcile/gql_definitions/common/saas_files.py +49 -0
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +15 -67
- reconcile/gql_definitions/fragments/saas_slo_document.py +82 -0
- reconcile/gql_definitions/introspection.json +249 -229
- reconcile/utils/slo_document_manager.py +278 -0
- {qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.2.
|
3
|
+
Version: 0.10.2.dev168
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
|
6
6
|
Project-URL: repository, https://github.com/app-sre/qontract-reconcile
|
{qontract_reconcile-0.10.2.dev167.dist-info → qontract_reconcile-0.10.2.dev168.dist-info}/RECORD
RENAMED
@@ -17,7 +17,7 @@ reconcile/dashdotdb_base.py,sha256=83ZWIf5JJk3P_D69y2TmXRcQr6ELJGlv10OM0h7fJVs,4
|
|
17
17
|
reconcile/dashdotdb_cso.py,sha256=QRK0YfIqO4rehs8btD3l_GXIO2ZIycTQEKEthBdB0xA,3639
|
18
18
|
reconcile/dashdotdb_dora.py,sha256=olQnGp4JYpoh1lQEf9kHc2y3bMaAIUXEB6eFohWH8Io,17859
|
19
19
|
reconcile/dashdotdb_dvo.py,sha256=lCkZ0iby6HrNQb-3kYb6xrt8wCjVUZYxKzz9SiStfHU,8946
|
20
|
-
reconcile/dashdotdb_slo.py,sha256=
|
20
|
+
reconcile/dashdotdb_slo.py,sha256=TvKdMOtUZcZP9QydcUJMKh0zURHgOMN_RTpQpCkD1Z8,3960
|
21
21
|
reconcile/database_access_manager.py,sha256=Z3aAmw2LsmMIIor-bOGzziVZdVNC82Gmw8oHBUAFf-8,25577
|
22
22
|
reconcile/deadmanssnitch.py,sha256=n-5W-djUgwzpmdDM4eQIZpkkDmHY0vndt-42LJXI4Y8,7491
|
23
23
|
reconcile/email_sender.py,sha256=38Wvl6WHqCwlqLx4oxVJOIeDmoJsyitD3g1F4jTkAj8,4246
|
@@ -227,7 +227,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
|
|
227
227
|
reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
228
228
|
reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
|
229
229
|
reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
230
|
-
reconcile/gql_definitions/introspection.json,sha256=
|
230
|
+
reconcile/gql_definitions/introspection.json,sha256=zD5QWpv9KYduZHr8a6dFoGz-oSHM1ItN1Trn02Lh7XQ,2297479
|
231
231
|
reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
232
232
|
reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
|
233
233
|
reconcile/gql_definitions/acs/acs_policies.py,sha256=bN5i4mks10Z23KJSj7jqp966Osq2dps4d-sPH9gjxEA,7008
|
@@ -295,7 +295,7 @@ reconcile/gql_definitions/common/pipeline_providers.py,sha256=9rpsqPuvj82B4ki56x
|
|
295
295
|
reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
|
296
296
|
reconcile/gql_definitions/common/quay_orgs.py,sha256=NhA8kqvVUDbrsryEvEL5mlIv5R3T4XNhSRXtfL_yptY,1788
|
297
297
|
reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
|
298
|
-
reconcile/gql_definitions/common/saas_files.py,sha256=
|
298
|
+
reconcile/gql_definitions/common/saas_files.py,sha256=d1L_S5LgCMa4QuAqZGQYTWb5L_nPCOxSEjU4O__OeBU,17728
|
299
299
|
reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
|
300
300
|
reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
|
301
301
|
reconcile/gql_definitions/common/slack_workspaces.py,sha256=2o0kgi4QiaRuNmZJnc_By4F6NsKIdRaXkrufRQw7Nok,1753
|
@@ -307,7 +307,7 @@ reconcile/gql_definitions/cost_report/app_names.py,sha256=fzqYXyiTSll359J1F1o7qa
|
|
307
307
|
reconcile/gql_definitions/cost_report/cost_namespaces.py,sha256=URRozAgSa9OnkqOCZf3MGH21_wcnsqYl0n-olXdjQH0,2286
|
308
308
|
reconcile/gql_definitions/cost_report/settings.py,sha256=0nhBDJ5MZ1m7XkNDGrRLmsnUbzqZ4WRh_DDEEzKhcxU,2153
|
309
309
|
reconcile/gql_definitions/dashdotdb_slo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
310
|
-
reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=
|
310
|
+
reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=a1zLeL_NCbK25fOeT1gZOch8HNPFcHhzVXQty3jKT_s,2430
|
311
311
|
reconcile/gql_definitions/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
312
312
|
reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py,sha256=5gTuAnR2rnx2k6Rn7FMEAzw6GCZ6F5HZbqkmJ9-3NI4,2244
|
313
313
|
reconcile/gql_definitions/dynatrace_token_provider/token_specs.py,sha256=XGsMuB8gowRpqJjkD_KRomx-1OswzyWbF4qjVdhionk,2555
|
@@ -350,6 +350,7 @@ reconcile/gql_definitions/fragments/prometheus_instance.py,sha256=12ltnV9kdEw6Ln
|
|
350
350
|
reconcile/gql_definitions/fragments/resource_limits_requirements.py,sha256=ucskQ_a8RxvFl5-IWxz5kk3g4-5Pvh_W4N3nLmuKxi0,744
|
351
351
|
reconcile/gql_definitions/fragments/resource_requests_requirements.py,sha256=TFKO4YALFPanSvZvIJFz0dCioBU7i73Q6hkDtGMvs9I,736
|
352
352
|
reconcile/gql_definitions/fragments/resource_values.py,sha256=-N2lNRhWp8PgocmIeX3U9f3l90Q97N2lXoq1pXdb_LE,742
|
353
|
+
reconcile/gql_definitions/fragments/saas_slo_document.py,sha256=6Ko_Kqny9gixPLKwr8RHL6DNx32rkNV24myurCVko-Q,2635
|
353
354
|
reconcile/gql_definitions/fragments/saas_target_namespace.py,sha256=6f6WaerElaRi9_Ro-0CyWUkMHsbXlm0h9YXklftBwag,3991
|
354
355
|
reconcile/gql_definitions/fragments/serviceaccount_token.py,sha256=2pG4rxAjvT-YsFBnm4zl301i7DCYznp99HOEGA-216I,1117
|
355
356
|
reconcile/gql_definitions/fragments/terraform_state.py,sha256=S5QuTR9YlvUObiU7hevS9ybxZEssWoRGqCR9YtGwePs,1024
|
@@ -658,6 +659,7 @@ reconcile/utils/secret_reader.py,sha256=MaP56KZaAE35EyYbgAitdm6fUSxdzWeGFSOym9qi
|
|
658
659
|
reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
|
659
660
|
reconcile/utils/sharding.py,sha256=DDBHfs5TT9UgjmzewiXUjbncnrPuceAZWeOA4veGa7s,843
|
660
661
|
reconcile/utils/slack_api.py,sha256=iaOFzv3wiZRhcgYK2NB4lsG6ymNsGk2MEuj0PgZVp7w,17355
|
662
|
+
reconcile/utils/slo_document_manager.py,sha256=CPgM2oH4AVzBqenakWo59R5yfwB62tnxSnSOHgir7l8,9500
|
661
663
|
reconcile/utils/smtp_client.py,sha256=0xefB4I9E5eBB-FlxFJYjvz3Kvuqi_K3Ma_Wk0NAQKM,2779
|
662
664
|
reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41Fg,2265
|
663
665
|
reconcile/utils/state.py,sha256=az4tBmZ0EdbFcAGiBVUxs3cr2-BVWsuDQiNTvjjQq8s,16378
|
@@ -804,7 +806,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
804
806
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
|
805
807
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
806
808
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
807
|
-
qontract_reconcile-0.10.2.
|
808
|
-
qontract_reconcile-0.10.2.
|
809
|
-
qontract_reconcile-0.10.2.
|
810
|
-
qontract_reconcile-0.10.2.
|
809
|
+
qontract_reconcile-0.10.2.dev168.dist-info/METADATA,sha256=wzA6vkcwYuN-6Jx92482hVcUXLcXr8p0BqSuz1gW-34,24627
|
810
|
+
qontract_reconcile-0.10.2.dev168.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
811
|
+
qontract_reconcile-0.10.2.dev168.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
812
|
+
qontract_reconcile-0.10.2.dev168.dist-info/RECORD,,
|
reconcile/dashdotdb_slo.py
CHANGED
@@ -1,11 +1,6 @@
|
|
1
|
-
from collections.abc import Iterable
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from math import isnan
|
4
1
|
from typing import Any
|
5
2
|
|
6
|
-
import jinja2
|
7
3
|
import requests
|
8
|
-
from requests import Response
|
9
4
|
from sretoolbox.utils import threaded
|
10
5
|
|
11
6
|
from reconcile.dashdotdb_base import (
|
@@ -13,9 +8,9 @@ from reconcile.dashdotdb_base import (
|
|
13
8
|
DashdotdbBase,
|
14
9
|
)
|
15
10
|
from reconcile.gql_definitions.dashdotdb_slo.slo_documents_query import (
|
16
|
-
SLODocumentV1,
|
17
11
|
query,
|
18
12
|
)
|
13
|
+
from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
|
19
14
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
20
15
|
get_app_interface_vault_settings,
|
21
16
|
)
|
@@ -24,40 +19,22 @@ from reconcile.utils.secret_reader import (
|
|
24
19
|
SecretReaderBase,
|
25
20
|
create_secret_reader,
|
26
21
|
)
|
22
|
+
from reconcile.utils.slo_document_manager import (
|
23
|
+
SLODetails,
|
24
|
+
SLODocumentManager,
|
25
|
+
)
|
27
26
|
|
28
27
|
QONTRACT_INTEGRATION = "dashdotdb-slo"
|
28
|
+
READ_TIMEOUT = 300
|
29
|
+
MAX_RETRIES = 2
|
29
30
|
|
30
31
|
|
31
|
-
def get_slo_documents() -> list[
|
32
|
+
def get_slo_documents() -> list[SLODocument]:
|
32
33
|
gqlapi = gql.get_api()
|
33
34
|
data = query(gqlapi.query)
|
34
35
|
return list(data.slo_documents or [])
|
35
36
|
|
36
37
|
|
37
|
-
@dataclass
|
38
|
-
class ServiceSLO:
|
39
|
-
name: str
|
40
|
-
sli_type: str
|
41
|
-
slo_doc_name: str
|
42
|
-
namespace_name: str
|
43
|
-
cluster_name: str
|
44
|
-
service_name: str
|
45
|
-
value: float
|
46
|
-
target: float
|
47
|
-
|
48
|
-
def dashdot_payload(self) -> dict[str, Any]:
|
49
|
-
return {
|
50
|
-
"name": self.name,
|
51
|
-
"SLIType": self.sli_type,
|
52
|
-
"SLODoc": {"name": self.slo_doc_name},
|
53
|
-
"namespace": {"name": self.namespace_name},
|
54
|
-
"cluster": {"name": self.cluster_name},
|
55
|
-
"service": {"name": self.service_name},
|
56
|
-
"value": self.value,
|
57
|
-
"target": self.target,
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
38
|
class DashdotdbSLO(DashdotdbBase):
|
62
39
|
def __init__(
|
63
40
|
self, dry_run: bool, thread_pool_size: int, secret_reader: SecretReaderBase
|
@@ -70,19 +47,28 @@ class DashdotdbSLO(DashdotdbBase):
|
|
70
47
|
secret_reader=secret_reader,
|
71
48
|
)
|
72
49
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
50
|
+
@staticmethod
|
51
|
+
def get_dash_dot_db_payload(slo: SLODetails) -> dict[str, Any]:
|
52
|
+
return {
|
53
|
+
"name": slo.slo.name,
|
54
|
+
"SLIType": slo.slo.sli_type,
|
55
|
+
"SLODoc": {"name": slo.slo_document_name},
|
56
|
+
"namespace": {"name": slo.namespace_name},
|
57
|
+
"cluster": {"name": slo.cluster_name},
|
58
|
+
"service": {"name": slo.service_name},
|
59
|
+
"value": slo.current_slo_value,
|
60
|
+
"target": slo.slo.slo_target,
|
61
|
+
}
|
85
62
|
|
63
|
+
def _post(self, service_slo: SLODetails) -> None:
|
64
|
+
LOG.debug(f"About to POST SLO JSON item to dashdotDB:\n{service_slo}\n")
|
65
|
+
slo_name = service_slo.slo.name
|
66
|
+
endpoint = f"{self.dashdotdb_url}/api/v1/serviceslometrics/{slo_name}"
|
67
|
+
if service_slo.slo.slo_target_unit == "percent_0_1":
|
68
|
+
service_slo.current_slo_value *= 100
|
69
|
+
service_slo.slo.slo_target *= 100
|
70
|
+
payload = self.get_dash_dot_db_payload(service_slo)
|
71
|
+
if not self.dry_run:
|
86
72
|
LOG.info("%s syncing slo %s", self.logmarker, slo_name)
|
87
73
|
try:
|
88
74
|
response = self._do_post(endpoint, payload)
|
@@ -94,127 +80,30 @@ class DashdotdbSLO(DashdotdbBase):
|
|
94
80
|
LOG.error("%s error posting %s - %s", self.logmarker, slo_name, details)
|
95
81
|
|
96
82
|
LOG.info("%s slo %s synced", self.logmarker, slo_name)
|
97
|
-
return response
|
98
|
-
|
99
|
-
def _get_service_slo(self, slo_document: SLODocumentV1) -> list[ServiceSLO]:
|
100
|
-
LOG.debug("SLO: processing %s", slo_document.name)
|
101
|
-
result: list[ServiceSLO] = []
|
102
|
-
for namespace_access in slo_document.namespaces:
|
103
|
-
if (
|
104
|
-
namespace_access.slo_namespace
|
105
|
-
and namespace_access.prometheus_access is None
|
106
|
-
):
|
107
|
-
continue
|
108
|
-
|
109
|
-
ns = namespace_access.namespace
|
110
|
-
promtoken: str | None = None
|
111
|
-
username: str | None = None
|
112
|
-
password: str | None = None
|
113
|
-
if namespace_access.prometheus_access:
|
114
|
-
promurl = namespace_access.prometheus_access.url
|
115
|
-
if (
|
116
|
-
namespace_access.prometheus_access.username
|
117
|
-
and namespace_access.prometheus_access.password
|
118
|
-
):
|
119
|
-
username = self.secret_reader.read_secret(
|
120
|
-
namespace_access.prometheus_access.username
|
121
|
-
)
|
122
|
-
password = self.secret_reader.read_secret(
|
123
|
-
namespace_access.prometheus_access.password
|
124
|
-
)
|
125
|
-
else:
|
126
|
-
promurl = ns.cluster.prometheus_url
|
127
|
-
if not ns.cluster.automation_token:
|
128
|
-
LOG.error(
|
129
|
-
"namespace does not have automation token set %s - skipping", ns
|
130
|
-
)
|
131
|
-
continue
|
132
|
-
promtoken = self._get_automation_token(ns.cluster.automation_token)
|
133
|
-
for slo in slo_document.slos or []:
|
134
|
-
unit = slo.slo_target_unit
|
135
|
-
expr = slo.expr
|
136
|
-
template = jinja2.Template(expr)
|
137
|
-
window = slo.slo_parameters.window
|
138
|
-
promquery = template.render({"window": window})
|
139
|
-
|
140
|
-
try:
|
141
|
-
prom_response = self._promget(
|
142
|
-
url=promurl,
|
143
|
-
params={"query": (f"{promquery}")},
|
144
|
-
token=promtoken,
|
145
|
-
username=username,
|
146
|
-
password=password,
|
147
|
-
)
|
148
|
-
except requests.exceptions.ConnectionError as error:
|
149
|
-
# This can happen when prometheus is unreachable, or when running locally
|
150
|
-
# and some prometheus URL are openshift service names. The trick is to run
|
151
|
-
# with `oc port-forward` and update the local hosts file if we need to query those.
|
152
|
-
LOG.error(
|
153
|
-
f"{self.logmarker} Could not reach prometheus at {promurl}: {error}."
|
154
|
-
f"Skipping SLOs from SLO doc {slo_document.name}"
|
155
|
-
)
|
156
|
-
# cannot connect to this prometheus, skip all
|
157
|
-
raise
|
158
|
-
except requests.exceptions.HTTPError as error:
|
159
|
-
LOG.error(
|
160
|
-
f"{self.logmarker} Error wile querying {promurl}: {error}."
|
161
|
-
f"Skipping SLO '{slo.name} from SLO doc {slo_document.name}"
|
162
|
-
)
|
163
|
-
# it could be a query issue, keep processing other SLOs from this doc
|
164
|
-
continue
|
165
|
-
|
166
|
-
prom_result = prom_response["data"]["result"]
|
167
|
-
if not prom_result:
|
168
|
-
continue
|
169
|
-
|
170
|
-
slo_value = prom_result[0]["value"]
|
171
|
-
if not slo_value:
|
172
|
-
continue
|
173
|
-
|
174
|
-
slo_value = float(slo_value[1])
|
175
|
-
if isnan(slo_value):
|
176
|
-
LOG.warning(
|
177
|
-
f"{self.logmarker} Skipping SLO '{slo.name}' in SLO doc '{slo_document.name}'"
|
178
|
-
"as the obtained value is not a number (maybe a division by 0?)"
|
179
|
-
)
|
180
|
-
continue
|
181
|
-
slo_target = float(slo.slo_target)
|
182
|
-
|
183
|
-
# In Dash.DB we want to always store SLOs in percentages
|
184
|
-
if unit == "percent_0_1":
|
185
|
-
slo_value *= 100
|
186
|
-
slo_target *= 100
|
187
|
-
|
188
|
-
result.append(
|
189
|
-
ServiceSLO(
|
190
|
-
name=slo.name,
|
191
|
-
sli_type=slo.sli_type,
|
192
|
-
namespace_name=ns.name,
|
193
|
-
cluster_name=ns.cluster.name,
|
194
|
-
service_name=ns.app.name,
|
195
|
-
value=slo_value,
|
196
|
-
target=slo_target,
|
197
|
-
slo_doc_name=slo_document.name,
|
198
|
-
)
|
199
|
-
)
|
200
|
-
return result
|
201
83
|
|
202
84
|
def run(self) -> None:
|
203
85
|
slo_documents = get_slo_documents()
|
204
86
|
|
205
|
-
|
206
|
-
|
207
|
-
|
87
|
+
slo_document_manager = SLODocumentManager(
|
88
|
+
slo_documents=slo_documents,
|
89
|
+
secret_reader=self.secret_reader,
|
208
90
|
thread_pool_size=self.thread_pool_size,
|
91
|
+
read_timeout=READ_TIMEOUT,
|
92
|
+
max_retries=MAX_RETRIES,
|
209
93
|
)
|
210
94
|
|
95
|
+
slo_details_list = slo_document_manager.get_current_slo_list()
|
96
|
+
valid_slo_list = [slo for slo in slo_details_list if slo]
|
97
|
+
|
211
98
|
self._get_token()
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
99
|
+
try:
|
100
|
+
threaded.run(
|
101
|
+
func=self._post,
|
102
|
+
iterable=valid_slo_list,
|
103
|
+
thread_pool_size=self.thread_pool_size,
|
104
|
+
)
|
105
|
+
finally:
|
106
|
+
self._close_token()
|
218
107
|
|
219
108
|
|
220
109
|
def run(dry_run: bool = False, thread_pool_size: int = 10) -> None:
|
@@ -18,6 +18,7 @@ from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
|
18
18
|
)
|
19
19
|
|
20
20
|
from reconcile.gql_definitions.fragments.oc_connection_cluster import OcConnectionCluster
|
21
|
+
from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
|
21
22
|
from reconcile.gql_definitions.fragments.saas_target_namespace import SaasTargetNamespace
|
22
23
|
from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
|
23
24
|
|
@@ -53,6 +54,50 @@ fragment OcConnectionCluster on Cluster_v1 {
|
|
53
54
|
}
|
54
55
|
}
|
55
56
|
|
57
|
+
fragment SLODocument on SLODocument_v1 {
|
58
|
+
name
|
59
|
+
namespaces {
|
60
|
+
prometheusAccess {
|
61
|
+
url
|
62
|
+
username {
|
63
|
+
... VaultSecret
|
64
|
+
}
|
65
|
+
password {
|
66
|
+
... VaultSecret
|
67
|
+
}
|
68
|
+
}
|
69
|
+
namespace {
|
70
|
+
name
|
71
|
+
app {
|
72
|
+
name
|
73
|
+
}
|
74
|
+
cluster {
|
75
|
+
name
|
76
|
+
automationToken {
|
77
|
+
... VaultSecret
|
78
|
+
}
|
79
|
+
prometheusUrl
|
80
|
+
spec {
|
81
|
+
private
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
SLONamespace {
|
86
|
+
name
|
87
|
+
}
|
88
|
+
}
|
89
|
+
slos {
|
90
|
+
name
|
91
|
+
expr
|
92
|
+
SLIType
|
93
|
+
SLOParameters {
|
94
|
+
window
|
95
|
+
}
|
96
|
+
SLOTarget
|
97
|
+
SLOTargetUnit
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
56
101
|
fragment SaasTargetNamespace on Namespace_v1 {
|
57
102
|
name
|
58
103
|
labels
|
@@ -253,6 +298,9 @@ query SaasFiles {
|
|
253
298
|
namespace {
|
254
299
|
...SaasTargetNamespace
|
255
300
|
}
|
301
|
+
slos {
|
302
|
+
...SLODocument
|
303
|
+
}
|
256
304
|
namespaceSelector {
|
257
305
|
jsonPathSelectors {
|
258
306
|
include
|
@@ -512,6 +560,7 @@ class SaasResourceTemplateTargetV2(ConfiguredBaseModel):
|
|
512
560
|
path: Optional[str] = Field(..., alias="path")
|
513
561
|
name: Optional[str] = Field(..., alias="name")
|
514
562
|
namespace: Optional[SaasTargetNamespace] = Field(..., alias="namespace")
|
563
|
+
slos: Optional[list[SLODocument]] = Field(..., alias="slos")
|
515
564
|
namespace_selector: Optional[SaasResourceTemplateTargetNamespaceSelectorV1] = Field(..., alias="namespaceSelector")
|
516
565
|
provider: Optional[str] = Field(..., alias="provider")
|
517
566
|
ref: str = Field(..., alias="ref")
|
@@ -17,19 +17,11 @@ from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
|
17
17
|
Json,
|
18
18
|
)
|
19
19
|
|
20
|
-
from reconcile.gql_definitions.fragments.
|
20
|
+
from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
|
21
21
|
|
22
22
|
|
23
23
|
DEFINITION = """
|
24
|
-
fragment
|
25
|
-
path
|
26
|
-
field
|
27
|
-
version
|
28
|
-
format
|
29
|
-
}
|
30
|
-
|
31
|
-
query SLODocuments {
|
32
|
-
slo_documents: slo_document_v1 {
|
24
|
+
fragment SLODocument on SLODocument_v1 {
|
33
25
|
name
|
34
26
|
namespaces {
|
35
27
|
prometheusAccess {
|
@@ -71,6 +63,18 @@ query SLODocuments {
|
|
71
63
|
SLOTarget
|
72
64
|
SLOTargetUnit
|
73
65
|
}
|
66
|
+
}
|
67
|
+
|
68
|
+
fragment VaultSecret on VaultSecret_v1 {
|
69
|
+
path
|
70
|
+
field
|
71
|
+
version
|
72
|
+
format
|
73
|
+
}
|
74
|
+
|
75
|
+
query SLODocuments {
|
76
|
+
slo_documents: slo_document_v1 {
|
77
|
+
... SLODocument
|
74
78
|
}
|
75
79
|
}
|
76
80
|
"""
|
@@ -82,64 +86,8 @@ class ConfiguredBaseModel(BaseModel):
|
|
82
86
|
extra=Extra.forbid
|
83
87
|
|
84
88
|
|
85
|
-
class SLOExternalPrometheusAccessV1(ConfiguredBaseModel):
|
86
|
-
url: str = Field(..., alias="url")
|
87
|
-
username: Optional[VaultSecret] = Field(..., alias="username")
|
88
|
-
password: Optional[VaultSecret] = Field(..., alias="password")
|
89
|
-
|
90
|
-
|
91
|
-
class AppV1(ConfiguredBaseModel):
|
92
|
-
name: str = Field(..., alias="name")
|
93
|
-
|
94
|
-
|
95
|
-
class ClusterSpecV1(ConfiguredBaseModel):
|
96
|
-
private: bool = Field(..., alias="private")
|
97
|
-
|
98
|
-
|
99
|
-
class ClusterV1(ConfiguredBaseModel):
|
100
|
-
name: str = Field(..., alias="name")
|
101
|
-
automation_token: Optional[VaultSecret] = Field(..., alias="automationToken")
|
102
|
-
prometheus_url: str = Field(..., alias="prometheusUrl")
|
103
|
-
spec: Optional[ClusterSpecV1] = Field(..., alias="spec")
|
104
|
-
|
105
|
-
|
106
|
-
class NamespaceV1(ConfiguredBaseModel):
|
107
|
-
name: str = Field(..., alias="name")
|
108
|
-
app: AppV1 = Field(..., alias="app")
|
109
|
-
cluster: ClusterV1 = Field(..., alias="cluster")
|
110
|
-
|
111
|
-
|
112
|
-
class SLONamespacesV1_NamespaceV1(ConfiguredBaseModel):
|
113
|
-
name: str = Field(..., alias="name")
|
114
|
-
|
115
|
-
|
116
|
-
class SLONamespacesV1(ConfiguredBaseModel):
|
117
|
-
prometheus_access: Optional[SLOExternalPrometheusAccessV1] = Field(..., alias="prometheusAccess")
|
118
|
-
namespace: NamespaceV1 = Field(..., alias="namespace")
|
119
|
-
slo_namespace: Optional[SLONamespacesV1_NamespaceV1] = Field(..., alias="SLONamespace")
|
120
|
-
|
121
|
-
|
122
|
-
class SLODocumentSLOSLOParametersV1(ConfiguredBaseModel):
|
123
|
-
window: str = Field(..., alias="window")
|
124
|
-
|
125
|
-
|
126
|
-
class SLODocumentSLOV1(ConfiguredBaseModel):
|
127
|
-
name: str = Field(..., alias="name")
|
128
|
-
expr: str = Field(..., alias="expr")
|
129
|
-
sli_type: str = Field(..., alias="SLIType")
|
130
|
-
slo_parameters: SLODocumentSLOSLOParametersV1 = Field(..., alias="SLOParameters")
|
131
|
-
slo_target: float = Field(..., alias="SLOTarget")
|
132
|
-
slo_target_unit: str = Field(..., alias="SLOTargetUnit")
|
133
|
-
|
134
|
-
|
135
|
-
class SLODocumentV1(ConfiguredBaseModel):
|
136
|
-
name: str = Field(..., alias="name")
|
137
|
-
namespaces: list[SLONamespacesV1] = Field(..., alias="namespaces")
|
138
|
-
slos: Optional[list[SLODocumentSLOV1]] = Field(..., alias="slos")
|
139
|
-
|
140
|
-
|
141
89
|
class SLODocumentsQueryData(ConfiguredBaseModel):
|
142
|
-
slo_documents: Optional[list[
|
90
|
+
slo_documents: Optional[list[SLODocument]] = Field(..., alias="slo_documents")
|
143
91
|
|
144
92
|
|
145
93
|
def query(query_func: Callable, **kwargs: Any) -> SLODocumentsQueryData:
|
@@ -0,0 +1,82 @@
|
|
1
|
+
"""
|
2
|
+
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
|
3
|
+
"""
|
4
|
+
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
|
5
|
+
from datetime import datetime # noqa: F401 # pylint: disable=W0611
|
6
|
+
from enum import Enum # noqa: F401 # pylint: disable=W0611
|
7
|
+
from typing import ( # noqa: F401 # pylint: disable=W0611
|
8
|
+
Any,
|
9
|
+
Optional,
|
10
|
+
Union,
|
11
|
+
)
|
12
|
+
|
13
|
+
from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
14
|
+
BaseModel,
|
15
|
+
Extra,
|
16
|
+
Field,
|
17
|
+
Json,
|
18
|
+
)
|
19
|
+
|
20
|
+
from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
|
21
|
+
|
22
|
+
|
23
|
+
class ConfiguredBaseModel(BaseModel):
|
24
|
+
class Config:
|
25
|
+
smart_union=True
|
26
|
+
extra=Extra.forbid
|
27
|
+
|
28
|
+
|
29
|
+
class SLOExternalPrometheusAccessV1(ConfiguredBaseModel):
|
30
|
+
url: str = Field(..., alias="url")
|
31
|
+
username: Optional[VaultSecret] = Field(..., alias="username")
|
32
|
+
password: Optional[VaultSecret] = Field(..., alias="password")
|
33
|
+
|
34
|
+
|
35
|
+
class AppV1(ConfiguredBaseModel):
|
36
|
+
name: str = Field(..., alias="name")
|
37
|
+
|
38
|
+
|
39
|
+
class ClusterSpecV1(ConfiguredBaseModel):
|
40
|
+
private: bool = Field(..., alias="private")
|
41
|
+
|
42
|
+
|
43
|
+
class ClusterV1(ConfiguredBaseModel):
|
44
|
+
name: str = Field(..., alias="name")
|
45
|
+
automation_token: Optional[VaultSecret] = Field(..., alias="automationToken")
|
46
|
+
prometheus_url: str = Field(..., alias="prometheusUrl")
|
47
|
+
spec: Optional[ClusterSpecV1] = Field(..., alias="spec")
|
48
|
+
|
49
|
+
|
50
|
+
class NamespaceV1(ConfiguredBaseModel):
|
51
|
+
name: str = Field(..., alias="name")
|
52
|
+
app: AppV1 = Field(..., alias="app")
|
53
|
+
cluster: ClusterV1 = Field(..., alias="cluster")
|
54
|
+
|
55
|
+
|
56
|
+
class SLONamespacesV1_NamespaceV1(ConfiguredBaseModel):
|
57
|
+
name: str = Field(..., alias="name")
|
58
|
+
|
59
|
+
|
60
|
+
class SLONamespacesV1(ConfiguredBaseModel):
|
61
|
+
prometheus_access: Optional[SLOExternalPrometheusAccessV1] = Field(..., alias="prometheusAccess")
|
62
|
+
namespace: NamespaceV1 = Field(..., alias="namespace")
|
63
|
+
slo_namespace: Optional[SLONamespacesV1_NamespaceV1] = Field(..., alias="SLONamespace")
|
64
|
+
|
65
|
+
|
66
|
+
class SLODocumentSLOSLOParametersV1(ConfiguredBaseModel):
|
67
|
+
window: str = Field(..., alias="window")
|
68
|
+
|
69
|
+
|
70
|
+
class SLODocumentSLOV1(ConfiguredBaseModel):
|
71
|
+
name: str = Field(..., alias="name")
|
72
|
+
expr: str = Field(..., alias="expr")
|
73
|
+
sli_type: str = Field(..., alias="SLIType")
|
74
|
+
slo_parameters: SLODocumentSLOSLOParametersV1 = Field(..., alias="SLOParameters")
|
75
|
+
slo_target: float = Field(..., alias="SLOTarget")
|
76
|
+
slo_target_unit: str = Field(..., alias="SLOTargetUnit")
|
77
|
+
|
78
|
+
|
79
|
+
class SLODocument(ConfiguredBaseModel):
|
80
|
+
name: str = Field(..., alias="name")
|
81
|
+
namespaces: list[SLONamespacesV1] = Field(..., alias="namespaces")
|
82
|
+
slos: Optional[list[SLODocumentSLOV1]] = Field(..., alias="slos")
|