qontract-reconcile 0.10.1rc1014__py3-none-any.whl → 0.10.1rc1016__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.1rc1014
3
+ Version: 0.10.1rc1016
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
@@ -181,7 +181,7 @@ reconcile/cna/assets/asset_factory.py,sha256=7T7X_J6xIsoGETqBRI45_EyIKEdQcnRPt_G
181
181
  reconcile/cna/assets/null.py,sha256=85mVh97atCoC0aLuX47poTZiyOthmziJeBsUw0c924w,1658
182
182
  reconcile/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
183
  reconcile/dynatrace_token_provider/dependencies.py,sha256=41q05A4C_eS3E8-MR4veeMxtQNsPoGdxmEa3d-OKxq4,2814
184
- reconcile/dynatrace_token_provider/integration.py,sha256=ffH4BpMNb3AafwengwzurZ-aiztGP1MUlnVU4FnO3IY,21540
184
+ reconcile/dynatrace_token_provider/integration.py,sha256=QY-k5vsbBOm80yW_RB6G2JZD5NY21zCyqHigos7GjRM,20876
185
185
  reconcile/dynatrace_token_provider/metrics.py,sha256=xiKkl8fTEBQaXJelGCPNTZhHAWdO1M3pCXNr_Tei63c,1285
186
186
  reconcile/dynatrace_token_provider/model.py,sha256=gkpqo5rRRueBXnIMjp4EEHqBUBuU65TRI8zpdb8GJ0A,241
187
187
  reconcile/dynatrace_token_provider/ocm.py,sha256=iHMsgbsLs-dlrB9UXmWNDF7E4UDe49JOsLa9rnowKfo,4282
@@ -644,7 +644,7 @@ reconcile/unleash_feature_toggles/integration.py,sha256=nx7BhtzCsTfPbOp60vI5MkNw
644
644
  reconcile/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
645
645
  reconcile/utils/aggregated_list.py,sha256=km0xadW0jO4G_CqZPsXmoBURQ8c90FaTu5x4X1K1cZs,3357
646
646
  reconcile/utils/amtool.py,sha256=ngtBuVPETH6oAy5RnKzvreVbjwQCaATS_PYYwBprzjQ,2288
647
- reconcile/utils/aws_api.py,sha256=C90pODy5UB2YRV2Yd9Z4J5aTnMZk1CZv9YxbCN0I1-4,66822
647
+ reconcile/utils/aws_api.py,sha256=FHE7tVN91ZAVDARN9EYr7kY3kB6UWtvZSlsvHcDyzx8,66830
648
648
  reconcile/utils/aws_helper.py,sha256=MDbv5jrNdqqJ5pfBxniGdJXBBO_EYc2_Uf2w9ZzeMNs,2854
649
649
  reconcile/utils/batches.py,sha256=TtEm64a8lWhFuNbUVpFEmXVdU2Q0sTBrP_I0Cjbgh7g,320
650
650
  reconcile/utils/binary.py,sha256=7MaAFBpzuBUTJ_aA6G6-eult_BPMVyiXbBLD0Y6F-DM,2301
@@ -716,7 +716,7 @@ reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41F
716
716
  reconcile/utils/state.py,sha256=a_EO5u7__Pqd0_E3MqzUttJ-0xRtuxcNx5oQi5WIahI,16392
717
717
  reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
718
718
  reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
719
- reconcile/utils/terraform_client.py,sha256=QTLRB33dWOlf2AmZPntx3WWBV8d_-cwMZyLKd7eqclk,34176
719
+ reconcile/utils/terraform_client.py,sha256=4eYKaKfG5wYfR--e1jHpmoMq36Q-JX1_WtT916wlMVw,34669
720
720
  reconcile/utils/terrascript_aws_client.py,sha256=1JgXcCF_-xbaAg7V9qihL1Xz5okQlSSrT1DeXGducHc,278037
721
721
  reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
722
722
  reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
@@ -744,7 +744,7 @@ reconcile/utils/clusterhealth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
744
744
  reconcile/utils/clusterhealth/providerbase.py,sha256=DXomGYogckBLqWtXn0PXU0hWYxB6K0F7ernldrkHhVY,1140
745
745
  reconcile/utils/clusterhealth/telemeter.py,sha256=PllSLsJXvGNatmTF4mxCNPVbDrpr_MPk0m5pWj-LT6g,1534
746
746
  reconcile/utils/dynatrace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
747
- reconcile/utils/dynatrace/client.py,sha256=siVDdCQeLaWm4W1T-QKnFwlotPmXmZfpyoe3pXowBt8,2760
747
+ reconcile/utils/dynatrace/client.py,sha256=dVaTwIlLhutv_2sxL_ISIQkN5br1Tfm14dhVP_hwePI,2834
748
748
  reconcile/utils/glitchtip/__init__.py,sha256=FT6iBhGqoe7KExFdbgL8AYUb64iW_4snF5__Dcl7yt0,258
749
749
  reconcile/utils/glitchtip/client.py,sha256=ovh4tx-ajlihjvcq6nyY4chulbuMJYvzDPv9j9CuAKM,7867
750
750
  reconcile/utils/glitchtip/models.py,sha256=uHbCK9-RWgxNYUAkEHXRAZRDDZW7jkOFFt9MdlqN4bU,6481
@@ -859,8 +859,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
859
859
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
860
860
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
861
861
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
862
- qontract_reconcile-0.10.1rc1014.dist-info/METADATA,sha256=_oYiLMwp1_SSIsoW1g1574AcwpLZcBG_NwIFvcUG_XU,2263
863
- qontract_reconcile-0.10.1rc1014.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
864
- qontract_reconcile-0.10.1rc1014.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
865
- qontract_reconcile-0.10.1rc1014.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
866
- qontract_reconcile-0.10.1rc1014.dist-info/RECORD,,
862
+ qontract_reconcile-0.10.1rc1016.dist-info/METADATA,sha256=yZiOVjfUvuD98NWXAJmjOZenh3UfAagM6WdkE9BQ1xo,2263
863
+ qontract_reconcile-0.10.1rc1016.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
864
+ qontract_reconcile-0.10.1rc1016.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
865
+ qontract_reconcile-0.10.1rc1016.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
866
+ qontract_reconcile-0.10.1rc1016.dist-info/RECORD,,
@@ -96,7 +96,7 @@ class DynatraceTokenProviderIntegration(
96
96
  for cluster in clusters
97
97
  if cluster.organization_id in self.params.ocm_organization_ids
98
98
  ]
99
- existing_dtp_tokens = {}
99
+ existing_dtp_tokens: dict[str, dict[str, str]] = {}
100
100
 
101
101
  for cluster in clusters:
102
102
  try:
@@ -139,7 +139,7 @@ class DynatraceTokenProviderIntegration(
139
139
  continue
140
140
  if tenant_id not in existing_dtp_tokens:
141
141
  existing_dtp_tokens[tenant_id] = (
142
- dt_client.get_token_ids_for_name_prefix(
142
+ dt_client.get_token_ids_map_for_name_prefix(
143
143
  prefix="dtp-"
144
144
  )
145
145
  )
@@ -172,7 +172,7 @@ class DynatraceTokenProviderIntegration(
172
172
  cluster: Cluster,
173
173
  dt_client: DynatraceClient,
174
174
  ocm_client: OCMClient,
175
- existing_dtp_tokens: Iterable[str],
175
+ existing_dtp_tokens: Mapping[str, str],
176
176
  tenant_id: str,
177
177
  token_spec: DynatraceTokenProviderTokenSpecV1,
178
178
  ) -> None:
@@ -281,7 +281,7 @@ class DynatraceTokenProviderIntegration(
281
281
  dry_run: bool,
282
282
  current_k8s_secrets: Iterable[K8sSecret],
283
283
  desired_spec: DynatraceTokenProviderTokenSpecV1,
284
- existing_dtp_tokens: Iterable[str],
284
+ existing_dtp_tokens: Mapping[str, str],
285
285
  dt_client: DynatraceClient,
286
286
  cluster_uuid: str,
287
287
  ) -> tuple[bool, Iterable[K8sSecret]]:
@@ -377,15 +377,12 @@ class DynatraceTokenProviderIntegration(
377
377
  raise e
378
378
  return manifest
379
379
 
380
- def get_secrets_from_syncset(
381
- self, syncset: Mapping[str, Any], token_spec: DynatraceTokenProviderTokenSpecV1
380
+ def get_secrets_from_data(
381
+ self,
382
+ secret_data_by_name: Mapping[str, Any],
383
+ token_spec: DynatraceTokenProviderTokenSpecV1,
382
384
  ) -> list[K8sSecret]:
383
385
  secrets: list[K8sSecret] = []
384
- secret_data_by_name = {
385
- resource.get("metadata", {}).get("name"): resource.get("data", {})
386
- for resource in syncset.get("resources", [])
387
- if resource.get("kind") == "Secret"
388
- }
389
386
  for secret in token_spec.secrets:
390
387
  secret_data = secret_data_by_name.get(secret.name)
391
388
  if secret_data:
@@ -414,42 +411,29 @@ class DynatraceTokenProviderIntegration(
414
411
  )
415
412
  return secrets
416
413
 
414
+ def get_secrets_from_syncset(
415
+ self, syncset: Mapping[str, Any], token_spec: DynatraceTokenProviderTokenSpecV1
416
+ ) -> list[K8sSecret]:
417
+ secret_data_by_name = {
418
+ resource.get("metadata", {}).get("name"): resource.get("data", {})
419
+ for resource in syncset.get("resources", [])
420
+ if resource.get("kind") == "Secret"
421
+ }
422
+ return self.get_secrets_from_data(
423
+ secret_data_by_name=secret_data_by_name, token_spec=token_spec
424
+ )
425
+
417
426
  def get_secrets_from_manifest(
418
427
  self, manifest: Mapping[str, Any], token_spec: DynatraceTokenProviderTokenSpecV1
419
428
  ) -> list[K8sSecret]:
420
- secrets: list[K8sSecret] = []
421
429
  secret_data_by_name = {
422
430
  resource.get("metadata", {}).get("name"): resource.get("data", {})
423
431
  for resource in manifest.get("workloads", [])
424
432
  if resource.get("kind") == "Secret"
425
433
  }
426
- for secret in token_spec.secrets:
427
- secret_data = secret_data_by_name.get(secret.name)
428
- if secret_data:
429
- tokens = []
430
- for token in secret.tokens:
431
- token_id = self.base64_decode(
432
- secret_data.get(f"{token.key_name_in_secret}Id", "")
433
- )
434
- token_value = self.base64_decode(
435
- secret_data.get(token.key_name_in_secret, "")
436
- )
437
- tokens.append(
438
- DynatraceAPIToken(
439
- id=token_id,
440
- token=token_value,
441
- name=token.name,
442
- secret_key=token.key_name_in_secret,
443
- )
444
- )
445
- secrets.append(
446
- K8sSecret(
447
- secret_name=secret.name,
448
- namespace_name=secret.namespace,
449
- tokens=tokens,
450
- )
451
- )
452
- return secrets
434
+ return self.get_secrets_from_data(
435
+ secret_data_by_name=secret_data_by_name, token_spec=token_spec
436
+ )
453
437
 
454
438
  def construct_secrets_data(
455
439
  self,
@@ -1646,7 +1646,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1646
1646
  parameters = {}
1647
1647
  for page in paginator.paginate(DBParameterGroupName=db_parameter_group_name):
1648
1648
  for param in page.get("Parameters", []):
1649
- parameters[param["ParameterName"]] = param["ParameterValue"]
1649
+ parameters[param["ParameterName"]] = param.get("ParameterValue", "")
1650
1650
  return parameters
1651
1651
 
1652
1652
  def get_organization_billing_account(self, account_name: str) -> str:
@@ -49,14 +49,16 @@ class DynatraceClient:
49
49
  ) from e
50
50
  return DynatraceAPITokenCreated(token=token.token, id=token.id)
51
51
 
52
- def get_token_ids_for_name_prefix(self, prefix: str) -> list[str]:
52
+ def get_token_ids_map_for_name_prefix(self, prefix: str) -> dict[str, str]:
53
53
  try:
54
54
  dt_tokens = self._api.tokens.list()
55
55
  except Exception as e:
56
56
  raise DynatraceTokenRetrievalError(
57
57
  f"{self._environment_url=} Failed to retrieve tokens for {prefix=}", e
58
58
  ) from e
59
- return [token.id for token in dt_tokens if token.name.startswith(prefix)]
59
+ return {
60
+ token.id: token.name for token in dt_tokens if token.name.startswith(prefix)
61
+ }
60
62
 
61
63
  def get_token_by_id(self, token_id: str) -> DynatraceAPIToken:
62
64
  try:
@@ -67,10 +69,11 @@ class DynatraceClient:
67
69
  ) from e
68
70
  return DynatraceAPIToken(id=token.id, scopes=token.scopes)
69
71
 
70
- def update_token_scopes(self, token_id: str, scopes: list[str]) -> None:
72
+ def update_token(self, token_id: str, name: str, scopes: list[str]) -> None:
71
73
  try:
72
74
  self._api.tokens.put(
73
75
  token_id=token_id,
76
+ name=name,
74
77
  api_token=ApiTokenUpdate(
75
78
  scopes=scopes,
76
79
  ),
@@ -772,40 +772,45 @@ class TerraformClient: # pylint: disable=too-many-public-methods
772
772
  None,
773
773
  )
774
774
  if target is None:
775
- raise ValueError(
775
+ logging.error(
776
776
  f"Cannot upgrade RDS instance: {resource_name} "
777
777
  f"from {before_version} to {after_version}"
778
778
  )
779
+ return
779
780
  allow_major_version_upgrade = after.get(
780
781
  "allow_major_version_upgrade",
781
782
  False,
782
783
  )
783
784
  if target["IsMajorVersionUpgrade"] and not allow_major_version_upgrade:
784
- raise ValueError(
785
+ logging.error(
785
786
  "allow_major_version_upgrade is not enabled for upgrading RDS instance: "
786
787
  f"{resource_name} to a new major version."
787
788
  )
789
+ return
788
790
 
789
- blue_green_update = after.get("blue_green_update", {}).get("enabled", False)
790
- if blue_green_update:
791
+ blue_green_update = after.get("blue_green_update", [])
792
+ if blue_green_update and blue_green_update[0]["enabled"]:
793
+ replica = before["replicas"] != [] or before["replicate_source_db"]
791
794
  self.validate_blue_green_update_requirements(
792
795
  account_name,
796
+ resource_name,
793
797
  engine,
794
- after_version,
795
- before["db_parameter_group_name"],
796
- before.get("replica_source"),
798
+ before_version,
799
+ replica,
800
+ before["parameter_group_name"],
797
801
  region_name,
798
802
  )
799
803
 
800
804
  def validate_blue_green_update_requirements(
801
805
  self,
802
- account_name,
803
- engine,
804
- version,
805
- parameter_group,
806
- replica_source,
807
- region_name,
808
- ):
806
+ account_name: str,
807
+ resource_name: str,
808
+ engine: str,
809
+ version: str,
810
+ replica: bool,
811
+ parameter_group: str,
812
+ region_name: str,
813
+ ) -> None:
809
814
  min_supported_versions = {
810
815
  "mysql": [pkg_version.parse("5.7"), pkg_version.parse("8.0.15")],
811
816
  "postgres": [
@@ -833,23 +838,29 @@ class TerraformClient: # pylint: disable=too-many-public-methods
833
838
  return False
834
839
 
835
840
  if not is_supported(engine, version):
836
- raise ValueError(
841
+ logging.error(
842
+ f"Cannot upgrade RDS instance: {resource_name}. "
837
843
  f"Engine version {version} is not supported for blue/green updates."
838
844
  )
845
+ return
839
846
 
840
- if replica_source:
841
- raise ValueError(
847
+ if replica:
848
+ logging.error(
849
+ f"Cannot upgrade RDS instance: {resource_name}. "
842
850
  "Blue/green updates are not supported for instances with read replicas."
843
851
  )
852
+ return
844
853
 
845
- if engine == "postgres" and parameter_group:
854
+ if engine == "postgres" and self._aws_api is not None:
846
855
  pg_details = self._aws_api.describe_db_parameter_group(
847
856
  account_name, parameter_group, region_name
848
857
  )
849
858
  if pg_details.get("rds.logical_replication") != "1":
850
- raise ValueError(
851
- f"Parameter group {parameter_group} does not have logical replication enabled."
859
+ logging.error(
860
+ f"Cannot upgrade RDS instance: {resource_name}. "
861
+ f"Blue/green updates require logical replication to be enabled in the Parameter group {parameter_group}."
852
862
  )
863
+ return
853
864
 
854
865
 
855
866
  class TerraformPlanFailed(Exception):