qontract-reconcile 0.10.1rc1132__py3-none-any.whl → 0.10.1rc1134__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc1132
3
+ Version: 0.10.1rc1134
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Home-page: https://github.com/app-sre/qontract-reconcile
6
6
  Author: Red Hat App-SRE Team
@@ -17,7 +17,7 @@ reconcile/dashdotdb_base.py,sha256=l34QDu1G96_Ctnh7ZXdxXgSeCE93GQMdLAkWxmN6vDA,4
17
17
  reconcile/dashdotdb_cso.py,sha256=IkI_KSZuH_kPn0cIQKXitJXiPPFSyHykrOuFy9h9ZpU,3643
18
18
  reconcile/dashdotdb_dora.py,sha256=YmfxD02tKUAQQzku2aj2DXv1oKkAr4V_2lrPVtTFGyI,17674
19
19
  reconcile/dashdotdb_dvo.py,sha256=lCkZ0iby6HrNQb-3kYb6xrt8wCjVUZYxKzz9SiStfHU,8946
20
- reconcile/dashdotdb_slo.py,sha256=S7j7xFeGaJkE82biWEdPu6ORCJEsJYNTDqcTzSl8AQY,6679
20
+ reconcile/dashdotdb_slo.py,sha256=QKKqLzA2f6zUjQvQ_6U4DObpSOB80C7h-NWXJhzQwME,7812
21
21
  reconcile/database_access_manager.py,sha256=FfyXnYcUdX54BYR_6B9PWFmhT8xdNrPCfoz3Q7q39tg,25646
22
22
  reconcile/deadmanssnitch.py,sha256=n-5W-djUgwzpmdDM4eQIZpkkDmHY0vndt-42LJXI4Y8,7491
23
23
  reconcile/email_sender.py,sha256=-5L-Ag_jaEYSzYRoMr52KQBRXz1E8yx9GqLbg2X4XFU,3533
@@ -283,7 +283,7 @@ reconcile/gql_definitions/cost_report/app_names.py,sha256=fzqYXyiTSll359J1F1o7qa
283
283
  reconcile/gql_definitions/cost_report/cost_namespaces.py,sha256=wV76J8Ynq0ObSfjSZQRLmCPUZ96frGc82Z5HPM_e4F4,2219
284
284
  reconcile/gql_definitions/cost_report/settings.py,sha256=0nhBDJ5MZ1m7XkNDGrRLmsnUbzqZ4WRh_DDEEzKhcxU,2153
285
285
  reconcile/gql_definitions/dashdotdb_slo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
286
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=zUa-CmpOwiymVmOV6KwDHH5mMl06p000320FcOas6hU,4315
286
+ reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=MYYpVOc8Ze9w7k6-tlUkp5OaPG_5bqHPS5FhfWTw00U,4335
287
287
  reconcile/gql_definitions/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
288
288
  reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py,sha256=5gTuAnR2rnx2k6Rn7FMEAzw6GCZ6F5HZbqkmJ9-3NI4,2244
289
289
  reconcile/gql_definitions/dynatrace_token_provider/token_specs.py,sha256=XGsMuB8gowRpqJjkD_KRomx-1OswzyWbF4qjVdhionk,2555
@@ -871,8 +871,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
871
871
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
872
872
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
873
873
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
874
- qontract_reconcile-0.10.1rc1132.dist-info/METADATA,sha256=lELtTQsA2H3TPWaNDegyi61VlMiwzJkt9pEYK0BdARA,2213
875
- qontract_reconcile-0.10.1rc1132.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
876
- qontract_reconcile-0.10.1rc1132.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
877
- qontract_reconcile-0.10.1rc1132.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
878
- qontract_reconcile-0.10.1rc1132.dist-info/RECORD,,
874
+ qontract_reconcile-0.10.1rc1134.dist-info/METADATA,sha256=HtnNYSBnLq4T0QQnHtSMfJvmXumkAWedjkfjqucyqAw,2213
875
+ qontract_reconcile-0.10.1rc1134.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
876
+ qontract_reconcile-0.10.1rc1134.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
877
+ qontract_reconcile-0.10.1rc1134.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
878
+ qontract_reconcile-0.10.1rc1134.dist-info/RECORD,,
@@ -1,5 +1,6 @@
1
1
  from collections.abc import Iterable
2
2
  from dataclasses import dataclass
3
+ from math import isnan
3
4
  from typing import Any
4
5
 
5
6
  import jinja2
@@ -83,10 +84,13 @@ class DashdotdbSLO(DashdotdbBase):
83
84
  continue
84
85
 
85
86
  LOG.info("%s syncing slo %s", self.logmarker, slo_name)
86
- response = self._do_post(endpoint, payload)
87
87
  try:
88
+ response = self._do_post(endpoint, payload)
88
89
  response.raise_for_status()
89
- except requests.exceptions.HTTPError as details:
90
+ except (
91
+ requests.exceptions.HTTPError,
92
+ requests.exceptions.InvalidJSONError,
93
+ ) as details:
90
94
  LOG.error("%s error posting %s - %s", self.logmarker, slo_name, details)
91
95
 
92
96
  LOG.info("%s slo %s synced", self.logmarker, slo_name)
@@ -96,10 +100,10 @@ class DashdotdbSLO(DashdotdbBase):
96
100
  LOG.debug("SLO: processing %s", slo_document.name)
97
101
  result: list[ServiceSLO] = []
98
102
  for namespace_access in slo_document.namespaces:
99
- # TODO: APPSRE-8513 Dashdotdb SLO collector should deal with
100
- # namespaceTargets. This `if` is a temporary workaround until
101
- # APPSRE-8513 is implemented.
102
- if namespace_access.slo_namespace:
103
+ if (
104
+ namespace_access.slo_namespace
105
+ and namespace_access.prometheus_access is None
106
+ ):
103
107
  continue
104
108
 
105
109
  ns = namespace_access.namespace
@@ -108,12 +112,16 @@ class DashdotdbSLO(DashdotdbBase):
108
112
  password: str | None = None
109
113
  if namespace_access.prometheus_access:
110
114
  promurl = namespace_access.prometheus_access.url
111
- username = self.secret_reader.read_secret(
115
+ if (
112
116
  namespace_access.prometheus_access.username
113
- )
114
- password = self.secret_reader.read_secret(
115
- namespace_access.prometheus_access.password
116
- )
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
+ )
117
125
  else:
118
126
  promurl = ns.cluster.prometheus_url
119
127
  if not ns.cluster.automation_token:
@@ -128,13 +136,22 @@ class DashdotdbSLO(DashdotdbBase):
128
136
  template = jinja2.Template(expr)
129
137
  window = slo.slo_parameters.window
130
138
  promquery = template.render({"window": window})
131
- prom_response = self._promget(
132
- url=promurl,
133
- params={"query": (f"{promquery}")},
134
- token=promtoken,
135
- username=username,
136
- password=password,
137
- )
139
+ try:
140
+ prom_response = self._promget(
141
+ url=promurl,
142
+ params={"query": (f"{promquery}")},
143
+ token=promtoken,
144
+ username=username,
145
+ password=password,
146
+ )
147
+ except requests.exceptions.ConnectionError as error:
148
+ # This can happen when prometheus is unreachable, or when running locally
149
+ # and some prometheus URL are openshift service names. The trick is to run
150
+ # with `oc port-forward` and update the local hosts file if we need to query those.
151
+ LOG.error(
152
+ f"{self.logmarker} Could not reach prometheus at {promurl}: {error}. Skipping {slo.name}"
153
+ )
154
+ raise
138
155
  prom_result = prom_response["data"]["result"]
139
156
  if not prom_result:
140
157
  continue
@@ -144,6 +161,12 @@ class DashdotdbSLO(DashdotdbBase):
144
161
  continue
145
162
 
146
163
  slo_value = float(slo_value[1])
164
+ if isnan(slo_value):
165
+ LOG.warning(
166
+ f"{self.logmarker} Skipping SLO '{slo.name}' in SLO doc '{slo_document.name}'"
167
+ "as the obtained value is not a number (maybe a division by 0?)"
168
+ )
169
+ continue
147
170
  slo_target = float(slo.slo_target)
148
171
 
149
172
  # In Dash.DB we want to always store SLOs in percentages
@@ -84,8 +84,8 @@ class ConfiguredBaseModel(BaseModel):
84
84
 
85
85
  class SLOExternalPrometheusAccessV1(ConfiguredBaseModel):
86
86
  url: str = Field(..., alias="url")
87
- username: VaultSecret = Field(..., alias="username")
88
- password: VaultSecret = Field(..., alias="password")
87
+ username: Optional[VaultSecret] = Field(..., alias="username")
88
+ password: Optional[VaultSecret] = Field(..., alias="password")
89
89
 
90
90
 
91
91
  class AppV1(ConfiguredBaseModel):