qontract-reconcile 0.10.2.dev248__py3-none-any.whl → 0.10.2.dev249__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.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev248
3
+ Version: 0.10.2.dev249
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
@@ -103,7 +103,7 @@ reconcile/slack_base.py,sha256=I-msunWxfgu5bSwXYulGbtLjxUB_tRmTCAUCU-3nabI,3484
103
103
  reconcile/slack_usergroups.py,sha256=xFkVe67RXSUj8JvpfSFEiRdQzB0TnJJEHW_b5PEwLng,30213
104
104
  reconcile/sql_query.py,sha256=auZCWe6dytsDp83Imfo4zqkpMCLRXU007IUlPeUE3j4,26376
105
105
  reconcile/status.py,sha256=cY4IJFXemhxptRJqR4qaaOWqei9e4jgLXuVSGajMsjg,544
106
- reconcile/status_board.py,sha256=Hxx6sFFyPTNi6zY-qlAco9OqPvdx6Kbgce0DunDUsNQ,15838
106
+ reconcile/status_board.py,sha256=wDto8vVFXHLIGwh4MfvsXTogVQ08JhqyDmhOyjjTJyk,15288
107
107
  reconcile/terraform_aws_route53.py,sha256=dQzzT46YhwRA902_H6pi-f7WlX4EaH187wXSdmJAUkQ,9958
108
108
  reconcile/terraform_cloudflare_dns.py,sha256=-aLEe2QnH5cJPu7HWqs-R9NmQ1NlFbcVUm0v7alVL3I,13431
109
109
  reconcile/terraform_cloudflare_resources.py,sha256=pq8Ieo5NmB-dYQ9X2F0s6iEoINMzhiqGw2yQK4ovok4,14980
@@ -797,7 +797,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
797
797
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
798
798
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
799
799
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
800
- qontract_reconcile-0.10.2.dev248.dist-info/METADATA,sha256=c3r-1NuxuH1uZzBEPnvPQsiGN3B6vQ6D0-BKyCLCcmo,23974
801
- qontract_reconcile-0.10.2.dev248.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
802
- qontract_reconcile-0.10.2.dev248.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
803
- qontract_reconcile-0.10.2.dev248.dist-info/RECORD,,
800
+ qontract_reconcile-0.10.2.dev249.dist-info/METADATA,sha256=gwjkeR4GBIHNQvWj-GxTlvIelNg9lny81cU3jDwHC8c,23974
801
+ qontract_reconcile-0.10.2.dev249.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
802
+ qontract_reconcile-0.10.2.dev249.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
803
+ qontract_reconcile-0.10.2.dev249.dist-info/RECORD,,
reconcile/status_board.py CHANGED
@@ -5,9 +5,7 @@ from abc import (
5
5
  )
6
6
  from collections.abc import Iterable, Mapping
7
7
  from enum import Enum
8
- from typing import (
9
- Optional,
10
- )
8
+ from itertools import chain
11
9
 
12
10
  from pydantic import BaseModel
13
11
 
@@ -122,11 +120,11 @@ class Product(AbstractStatusBoard):
122
120
 
123
121
 
124
122
  class Application(AbstractStatusBoard):
125
- product: Optional["Product"]
123
+ product: Product
126
124
  services: list["Service"] | None
127
125
 
128
126
  def create(self, ocm: OCMBaseClient) -> None:
129
- if self.product and self.product.id:
127
+ if self.product.id:
130
128
  spec = self.to_ocm_spec()
131
129
  self.id = create_application(ocm, spec)
132
130
  else:
@@ -147,7 +145,7 @@ class Application(AbstractStatusBoard):
147
145
  return f'Application: "{self.name}" "{self.fullname}"'
148
146
 
149
147
  def to_ocm_spec(self) -> ApplicationOCMSpec:
150
- product_id = self.product.id if self.product and self.product.id else ""
148
+ product_id = self.product.id or ""
151
149
  return {
152
150
  "name": self.name,
153
151
  "fullname": self.fullname,
@@ -160,18 +158,12 @@ class Application(AbstractStatusBoard):
160
158
 
161
159
 
162
160
  class Service(AbstractStatusBoard):
163
- # `application` here is used to create a flat map to easily compare state.
164
- # This field is optional so we can create the Service object without the
165
- # need to create an Application object first.
166
- # This filed is needed when we are creating a Service on teh OCM API.
167
- # This field is not used when we are mapping the services that belongs to an
168
- # application in that case we use the `services` field in Application class.
169
- application: Optional["Application"]
161
+ application: Application
170
162
  metadata: ServiceMetadataSpec
171
163
 
172
164
  def create(self, ocm: OCMBaseClient) -> None:
173
165
  spec = self.to_ocm_spec()
174
- if self.application and self.application.id:
166
+ if self.application.id:
175
167
  self.id = create_service(ocm, spec)
176
168
  else:
177
169
  logging.warning("Missing application id for service")
@@ -187,7 +179,7 @@ class Service(AbstractStatusBoard):
187
179
  logging.error(f'Trying to update Service "{self.name}" without id')
188
180
  return
189
181
  spec = self.to_ocm_spec()
190
- if self.application and self.application.id:
182
+ if self.application.id:
191
183
  update_service(ocm, self.id, spec)
192
184
  else:
193
185
  logging.warning("Missing application id for service")
@@ -196,9 +188,7 @@ class Service(AbstractStatusBoard):
196
188
  return f'Service: "{self.name}" "{self.fullname}"'
197
189
 
198
190
  def to_ocm_spec(self) -> ServiceOCMSpec:
199
- application_id = (
200
- self.application.id if self.application and self.application.id else ""
201
- )
191
+ application_id = self.application.id or ""
202
192
 
203
193
  return {
204
194
  "name": self.name,
@@ -281,21 +271,24 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
281
271
  logging.error(f'Product "{p.name}" has no id')
282
272
  continue
283
273
  p.applications = [
284
- Application(**a) for a in get_product_applications(ocm_api, p.id)
274
+ Application(**a, product=p)
275
+ for a in get_product_applications(ocm_api, p.id)
285
276
  ]
286
277
  for a in p.applications:
287
278
  if not a.id:
288
279
  logging.error(f'Application "{a.name}" has no id')
289
280
  continue
290
281
  a.services = [
291
- Service(**s) for s in get_application_services(ocm_api, a.id)
282
+ Service(**s, application=a)
283
+ for s in get_application_services(ocm_api, a.id)
292
284
  ]
293
285
 
294
286
  return products
295
287
 
296
288
  @staticmethod
297
289
  def desired_abstract_status_board_map(
298
- desired_product_apps: Mapping[str, set[str]], slodocs: list[SLODocumentV1]
290
+ desired_product_apps: Mapping[str, set[str]],
291
+ slodocs: list[SLODocumentV1],
299
292
  ) -> dict[str, AbstractStatusBoard]:
300
293
  """
301
294
  Returns a Mapping of all the AbstractStatusBoard data objects as dictionaries.
@@ -304,25 +297,26 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
304
297
  on Status Board OCM API.
305
298
  """
306
299
  desired_abstract_status_board_map: dict[str, AbstractStatusBoard] = {}
307
- for product, apps in desired_product_apps.items():
308
- desired_abstract_status_board_map[product] = Product(
309
- name=product, fullname=product, applications=[], metadata={}
300
+ for product_name, apps in desired_product_apps.items():
301
+ product = Product(
302
+ id=None, name=product_name, fullname=product_name, applications=[]
310
303
  )
304
+ desired_abstract_status_board_map[product_name] = product
311
305
  for a in apps:
312
- key = f"{product}/{a}"
306
+ key = f"{product_name}/{a}"
313
307
  desired_abstract_status_board_map[key] = Application(
308
+ id=None,
314
309
  name=a,
315
310
  fullname=key,
316
311
  services=[],
317
- product=desired_abstract_status_board_map[product],
318
- metadata={},
312
+ product=product,
319
313
  )
320
314
  for slodoc in slodocs:
321
315
  products = [
322
316
  ns.namespace.environment.product.name for ns in slodoc.namespaces
323
317
  ]
324
318
  for slo in slodoc.slos or []:
325
- for product in products:
319
+ for product_name in products:
326
320
  if slodoc.app.parent_app:
327
321
  app = f"{slodoc.app.parent_app.name}-{slodoc.app.name}"
328
322
  else:
@@ -330,8 +324,8 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
330
324
 
331
325
  # Check if the product or app is excluded from the desired list
332
326
  product_or_app_excluded = (
333
- product not in desired_product_apps
334
- or app not in desired_product_apps.get(product, set())
327
+ product_name not in desired_product_apps
328
+ or app not in desired_product_apps.get(product_name, set())
335
329
  )
336
330
 
337
331
  # Check if statusBoard label exists and is explicitly disabled
@@ -344,8 +338,8 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
344
338
  if product_or_app_excluded or not status_board_enabled:
345
339
  continue
346
340
 
347
- key = f"{product}/{app}/{slo.name}"
348
- metadata = {
341
+ key = f"{product_name}/{app}/{slo.name}"
342
+ metadata: ServiceMetadataSpec = {
349
343
  "sli_type": slo.sli_type,
350
344
  "sli_specification": slo.sli_specification,
351
345
  "slo_details": slo.slo_details,
@@ -354,11 +348,12 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
354
348
  "window": slo.slo_parameters.window,
355
349
  }
356
350
  desired_abstract_status_board_map[key] = Service(
351
+ id=None,
357
352
  name=slo.name,
358
353
  fullname=key,
359
354
  metadata=metadata,
360
355
  application=desired_abstract_status_board_map[
361
- f"{product}/{app}"
356
+ f"{product_name}/{app}"
362
357
  ],
363
358
  )
364
359
 
@@ -382,7 +377,6 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
382
377
  def get_diff(
383
378
  desired_abstract_status_board_map: Mapping[str, AbstractStatusBoard],
384
379
  current_abstract_status_board_map: Mapping[str, AbstractStatusBoard],
385
- current_products: Mapping[str, Product],
386
380
  ) -> list[StatusBoardHandler]:
387
381
  return_list: list[StatusBoardHandler] = []
388
382
 
@@ -391,6 +385,9 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
391
385
  desired_abstract_status_board_map,
392
386
  )
393
387
 
388
+ for pair in chain(diff_result.identical.values(), diff_result.change.values()):
389
+ pair.desired.id = pair.current.id
390
+
394
391
  return_list.extend(
395
392
  StatusBoardHandler(action=Action.create, status_board_object=o)
396
393
  for o in diff_result.add.values()
@@ -460,14 +457,9 @@ class StatusBoardExporterIntegration(QontractReconcileIntegration):
460
457
  current_abstract_status_board_map = self.current_abstract_status_board_map(
461
458
  current_products_applications_services
462
459
  )
463
-
464
- current_products = {
465
- p.name: p for p in current_products_applications_services
466
- }
467
460
  diff = self.get_diff(
468
461
  desired_abstract_status_board_map,
469
462
  current_abstract_status_board_map,
470
- current_products,
471
463
  )
472
464
 
473
465
  self.apply_diff(dry_run, ocm_api, diff)